hooks状态管理有利于再FC中更好的去管理全局状态,数据更多的是全局通用数据,如果只在组件内使用的数据,请使用useState
。
import createStore from 'unstate-hooks';
const store = createStore(data)
const { Provider, useStore, useStoreBy } = store;
推荐使用useStoreBy,对性能更好。
以下是最简单的一个例子,可以在任何Provider
包裹的元素中使用useStore
store.ts
import createStore from 'unstate-hooks';
const initData = {
number: 0
};
export default createStore(initData, true);
index.tsx
import store from "./store";
import Demo from './demo';
const { Provider } = store;
ReactDOM.render(
<Provider>
<Demo />
</Provider>,
document.getElementById("root")
);
demo.tsx
import store from "./store";
const { useStoreBy } = store;
export default function Demo() {
const [ data, update ] = useStoreBy('number');
return (
<div>
{data}
<button onClick={() => update(data + 1)}>+</button>
<button onClick={() => update(data - 1)}>-</button>
</div>
);
}
createStore
函数第二个参数为是否开启 debug 模式,设置true
可在打印台查看数据变化
createStore(initData, true);
用法上,useStoreBy
是对单个对象属性的操作,更新会重新渲染订阅到该属性的地方,而useStore
是对整个对象的操作,更新会重新渲染所有用到useStore
和useStoreBy
的地方
你可以用useStoreBy
去扩展任何你想做的,可以包装暴露更多的action
,把很多公用的业务代码抽离出来,形成更好复用,更加优雅的方式。例如下面自定义的useStore。
const useStoreWithActions = function() {
const [ data, update ] = useStoreBy('number');
const increment = () => {
update(data + 1)
}
const decrement = () => {
update(data - 1)
}
return {
data,
increment,
decrement
}
}
因为store
的data
是定义在context
里,但是context
的存在一个已知问题:
useContext doesn't let you subscribe to a part of the context value (or some memoized selector) without fully re-rendering
this Hook will trigger a rerender with the latest context value passed to that MyContext provider. Even if an ancestor uses React.memo or shouldComponentUpdate, a rerender will still happen starting at the component itself using useContext.
类似与官方的推荐做法,我们现在的做法是:createStore
默认会根据传入的对象拆解,生成多个context
,以达到更好的性能效果。