反应式声明似乎不起作用?还是我使用 'hooks' 的方式不对?
Reactive declarations seems not work? Or am I using the 'hooks' the wrong way?
我正在使用 svelte-navigator
编写 SPA Svelte 应用程序。我想在 pathname
更改时获取请求。
import { useLocation } from "svelte-navigator";
import { useCallApi } from "./hook";
const loc = useLocation();
const [resp, fetchPageData] = useCallApi(); // my `hooks` to call api
$: pathname = $loc.pathname;
$: loading = $resp.loading;
$: data = $resp.data;
$: {
console.log("loading changed", loading);
}
$: if (pathname) {
console.log(pathname);
fetchPageData(); // when pathname change, call a api
}
fetchPageData
在 pathname
每次更改时调用,但反应式声明($: loading
)不会每次都更新。
我使用 hooks
的方式是这样的:
import { writable } from 'svelte/store';
export function useCallApi() {
let result = writable({
loading: false,
data: 0,
});
const fakeFetch = async () => {
result.update(pre => ({
data: 0,
loading: true,
}));
await new Promise(r => setTimeout(r, 500));
result.update(pre => ({
data: Math.random(),
loading: false,
}));
};
return [result, fakeFetch];
}
在线演示是https://svelte.dev/repl/e367c0aa3c9743cb8a749f92f0239d59?version=3.32.1。
当单击 To a
或 To b
更改 pathname
时,反应式声明仅更新一次。
但是当单击按钮 trigger request
时,所有状态更新都符合我的预期。
我想知道这有什么问题,svelte
、svelte-navigator
或 my hooks
?为什么?
如果你能帮助我,我将不胜感激。
更新时间:2021-02-02
我的朋友发现 statements order
影响更新行为,这看起来有点像 。如果将 fetchPageData()
放在顶部,更新行为看起来不错。
import { useLocation } from "svelte-navigator";
import { useCallApi } from "./hook";
const loc = useLocation();
const [resp, fetchPageData] = useCallApi();
// the order is important which will affect the update behavior
$: if (pathname) {
console.log(pathname);
fetchPageData();
}
$: pathname = $loc.pathname;
$: loading = $resp.loading;
$: data = $resp.data;
$: {
console.log("loading changed", loading, $resp.loading);
}
我真的不知道为什么,但是当您将自动订阅 $
替换为 resp.subscribe()
时,它起作用了:
import { useLocation } from "svelte-navigator";
import { useCallApi } from "./hook";
const loc = useLocation();
const [resp, fetchPageData] = useCallApi(); // my `hooks` to call api
$: pathname = $loc.pathname;
let loading;
let data;
resp.subscribe( result => {
loading = result.loading;
data = result.data;
});
$: {
console.log("loading changed", loading);
}
$: if (pathname) {
console.log(pathname);
fetchPageData(); // when pathname change, call a api
}
你可以在这里试试:https://svelte.dev/repl/ca065fdc188e41938b8e3db0b8c61f20?version=3.32.1
我认为答案就在 svelte 执行响应语句的方式背后。
根据 : :
svelte batches all the changes to update them in the next update cycle, and before it updates the DOM, it will execute the reactive declarations to update the reactive variables.
当您从 a 更新您的路由器时,我认为编译后的代码在更新响应语句 $: loading = $resp.loading;
和 $: data = $resp.data;
之前等待承诺解析(在 hook.js
中),因此{ loading }
和 { data }
为 DOM。
我正在使用 svelte-navigator
编写 SPA Svelte 应用程序。我想在 pathname
更改时获取请求。
import { useLocation } from "svelte-navigator";
import { useCallApi } from "./hook";
const loc = useLocation();
const [resp, fetchPageData] = useCallApi(); // my `hooks` to call api
$: pathname = $loc.pathname;
$: loading = $resp.loading;
$: data = $resp.data;
$: {
console.log("loading changed", loading);
}
$: if (pathname) {
console.log(pathname);
fetchPageData(); // when pathname change, call a api
}
fetchPageData
在 pathname
每次更改时调用,但反应式声明($: loading
)不会每次都更新。
我使用 hooks
的方式是这样的:
import { writable } from 'svelte/store';
export function useCallApi() {
let result = writable({
loading: false,
data: 0,
});
const fakeFetch = async () => {
result.update(pre => ({
data: 0,
loading: true,
}));
await new Promise(r => setTimeout(r, 500));
result.update(pre => ({
data: Math.random(),
loading: false,
}));
};
return [result, fakeFetch];
}
在线演示是https://svelte.dev/repl/e367c0aa3c9743cb8a749f92f0239d59?version=3.32.1。
当单击 To a
或 To b
更改 pathname
时,反应式声明仅更新一次。
但是当单击按钮 trigger request
时,所有状态更新都符合我的预期。
我想知道这有什么问题,svelte
、svelte-navigator
或 my hooks
?为什么?
如果你能帮助我,我将不胜感激。
更新时间:2021-02-02
我的朋友发现 statements order
影响更新行为,这看起来有点像 fetchPageData()
放在顶部,更新行为看起来不错。
import { useLocation } from "svelte-navigator";
import { useCallApi } from "./hook";
const loc = useLocation();
const [resp, fetchPageData] = useCallApi();
// the order is important which will affect the update behavior
$: if (pathname) {
console.log(pathname);
fetchPageData();
}
$: pathname = $loc.pathname;
$: loading = $resp.loading;
$: data = $resp.data;
$: {
console.log("loading changed", loading, $resp.loading);
}
我真的不知道为什么,但是当您将自动订阅 $
替换为 resp.subscribe()
时,它起作用了:
import { useLocation } from "svelte-navigator";
import { useCallApi } from "./hook";
const loc = useLocation();
const [resp, fetchPageData] = useCallApi(); // my `hooks` to call api
$: pathname = $loc.pathname;
let loading;
let data;
resp.subscribe( result => {
loading = result.loading;
data = result.data;
});
$: {
console.log("loading changed", loading);
}
$: if (pathname) {
console.log(pathname);
fetchPageData(); // when pathname change, call a api
}
你可以在这里试试:https://svelte.dev/repl/ca065fdc188e41938b8e3db0b8c61f20?version=3.32.1
我认为答案就在 svelte 执行响应语句的方式背后。
根据 :
svelte batches all the changes to update them in the next update cycle, and before it updates the DOM, it will execute the reactive declarations to update the reactive variables.
当您从 a 更新您的路由器时,我认为编译后的代码在更新响应语句 $: loading = $resp.loading;
和 $: data = $resp.data;
之前等待承诺解析(在 hook.js
中),因此{ loading }
和 { data }
为 DOM。