跳转到主文档

useStaticModel

补充信息

如果想在组件里以 React Hook 的形式消费某个 Model,并能随时获取到当前最新的状态,但又不希望 Model 状态更新的时候,引起组件的 rerender,可以使用 useStaticModel

import { useStaticModel } from '@modern-js/runtime/model';

API

useStaticModel API 形式上与 useModel 完全一致。具体使用请参考 useModel

为了保证总是能获取到最新状态,注意不要对返回的 state 结构,state 上挂载了 get 方法,通过 state 才能拿到最新的值。

function App() {
// ❌ 不能解构 state,但可以解构 actions。
const [{ username }, { logout }] = useStaticModel(userModel);

// ✅ 这才是正确使用姿势。
const [state, { logout }] = useStaticModel(userModel);

useEffect(() => {
state.username
}, []);
}

示例

在性能敏感场景使用

react-three-fiber 建议不要在动画组件 UI 里绑定会快速变化的状态,否则会引起严重的性能问题。这种情况就可以选择使用 useStaticModel,因为它只会订阅状态,但绝不会引起视图的 rerender。

function ThreeComponent() {
const [state, actions] = useStaticModel(modelA);

useFrame(() => {
state.value // 假设初始化为 0
actions.setValue(1);
state.value // 这里会得到1
});
}

闭包函数消费

在编写组件的时候,消费 Model 获得的数据主要有两个用途,一是直接供视图消费,二是供组件内的一些闭包函数消费。

function App() {
const [state] = useModel(userModel);

useEffect(() => {
send('pageview', {user: state.user});
}, [state])

return <div>Hello</div>;
}

如上 App 组件消费了 userModel 的状态,但没有直接在 View 里使用,但 userModel 状态的改变却会引起 View 的 rerender,这是不符合预期的,这种情况可以使用 useStaticModel 进行优化。

function App() {
const [state] = useStaticModel(userModel);

useEffect(() => {
send('pageview', {user: state.user});
}, [state])

return <div>Hello</div>;
}