生命周期
规则
使用生命周期hooks时,必须遵守以下规则:
- 他们只能在
component$
里调用 - 他们只能在普通函数根层级/箭头函数context里被调用, 不能在条件块语句里调用。
- 他们只能被其他
use*$
方法调用, 用于组合
useHook() // <-- ❌ does not work
export default component$(() => {
useHook() // <-- ✅ does work
if (condition) {
useHook() // <-- ❌ does not work
}
const myQrl = $(() => useHook()) // <-- ✅ does work
return <button onClick$={() => useHook()}></button> // <-- ✅ does work
})
const useCustomHook = () => {
useHook() // <-- ✅ does work
}
useMount$()
useMount$()
可以注册一个hook,当组件创建完时,会执行这个hook。
useMount$()
会阻塞组件渲染 直到 useMount$()
回调 解析完。
(这对异步取数据和直到拿到数据再延迟渲染是有用的,保证了渲染的组件包含数据。)
同时 useMount$()
既可以在服务端也可以在客户端执行,
它只执行一次。(或者在客户端或者在服务端, 取决于组件首先在哪里渲染)
还有一个 useServerMount$()
hook 有同样的作用但只能在服务端使用。
Example
export const Cmp = component$(() => {
const store = useStore({
users: [],
});
useMount$(async () => {
// This code will run on component creation to fetch the data.
store.users = await db.requestUsers();
});
return (
<>
{store.users.map((user) => (
<User user={user} />
))}
</>
);
});
interface User {
name: string;
}
export function User(props: { user: User }) {
return <div>Name: {props.user.name}</div>;
}
useServerMount$()
useServerMount$()
注册一个server-mounted hook,只在第一次mounted时在服务端运行。
例子
export const Cmp = component$(() => {
const store = useStore({
users: [],
});
useServerMount$(async () => {
// This code will ONLY run once in the server, when the component is mounted
store.users = await db.requestUsers();
});
return (
<>
{store.users.map((user) => (
<User user={user} />
))}
</>
);
});
interface User {
name: string;
}
export function User(props: { user: User }) {
return <div>Name: {props.user.name}</div>;
}
useWatch$()
当跟踪的输入改变时 watchFn
重新运行。
使用 useWatch
跟踪一系列输入值的改变情况, 当这些输入有改变时,重新执行watchFn
。
watchFn
只有在输入变化的时候才执行。
为了跟踪这些输入,要使用track
函数包裹这些属性。
这样就会创建一个订阅。这个订阅会触发watchFn
函数重新执行。
还有一个 useClientEffect$()
hook 有同样的作用但只在客户端运行。
例子
useWatch
函数用来观察state.count
属性,state.count
变化了就会引起watchFn
执行。
而watchFn
执行又会更新state.doubleCount
的值,使其变为state.count
的两倍。
export const Cmp = component$(() => {
const store = useStore({
count: 1,
doubleCount: 0,
debounced: 0,
});
// Double count watch
useWatch$(({ track }) => {
const count = track(() => store.count);
store.doubleCount = 2 * count;
});
// Debouncer watch
useWatch$(({ track }) => {
const doubleCount = track(() => store.doubleCount);
const timer = setTimeout(() => {
store.debounced = doubleCount;
}, 2000);
return () => {
clearTimeout(timer);
};
});
return (
<>
<div>
{store.count} / {store.doubleCount}
</div>
<div>{store.debounced}</div>
</>
);
});
useClientEffect$()
当跟踪的输入改变时,重新运行watchFn
。
如果没有使用track
,它只执行一次。
例子
export const Timer = component$(() => {
const store = useStore({
count: 0,
});
useClientEffect$(() => {
// Only runs in the client
const timer = setInterval(() => {
store.count++;
}, 500);
return () => {
clearInterval(timer);
};
});
return <>{store.count}</>;
});