utquidem
Version:
The meta-framework suite designed from scratch for frontend-focused modern web development.
79 lines (58 loc) • 2.35 kB
Markdown
---
sidebar_position: 2
---
# useStaticModel
:::info 补充信息
如果想在组件里以 **React Hook** 的形式消费某个 **Model**,并能随时获取到当前最新的状态,但又不希望 **Model** 状态更新的时候,引起组件的 rerender,可以使用 `useStaticModel`。
```ts
import { useStaticModel } from '@modern-js/runtime/model';
```
:::
## API
`useStaticModel` API 形式上与 `useModel` 完全一致。具体使用请参考 [`useModel`](./use-model)。
为了保证总是能获取到最新状态,注意不要对返回的 `state` 结构,`state` 上挂载了 `get` 方法,通过 `state` 才能拿到最新的值。
```tsx
function App() {
// ❌ 不能解构 state,但可以解构 actions。
const [{ username }, { logout }] = useStaticModel(userModel);
// ✅ 这才是正确使用姿势。
const [state, { logout }] = useStaticModel(userModel);
useEffect(() => {
state.username
}, []);
}
```
## 示例
### 在性能敏感场景使用
如 [`react-three-fiber`](https://docs.pmnd.rs/react-three-fiber/advanced/pitfalls#never-bind-fast-state-reactive) 建议不要在动画组件 UI 里绑定会快速变化的状态,否则会引起严重的性能问题。这种情况就可以选择使用 `useStaticModel`,因为它只会订阅状态,但绝不会引起视图的 rerender。
```tsx
function ThreeComponent() {
const [state, actions] = useStaticModel(modelA);
useFrame(() => {
state.value // 假设初始化为 0
actions.setValue(1);
state.value // 这里会得到1
});
}
```
### 闭包函数消费
在编写组件的时候,消费 **Model** 获得的数据主要有两个用途,一是直接供视图消费,二是供组件内的一些闭包函数消费。
```tsx
function App() {
const [state] = useModel(userModel);
useEffect(() => {
send('pageview', {user: state.user});
}, [state])
return <div>Hello</div>;
}
```
如上 `App` 组件消费了 `userModel` 的状态,但没有直接在 View 里使用,但 `userModel` 状态的改变却会引起 View 的 rerender,这是不符合预期的,这种情况可以使用 `useStaticModel` 进行优化。
```tsx
function App() {
const [state] = useStaticModel(userModel);
useEffect(() => {
send('pageview', {user: state.user});
}, [state])
return <div>Hello</div>;
}
```