iostore
iostore copied to clipboard
不必要渲染的如何解决?
因为根据store名称来收集setState,从而触发渲染的 store任何一个属性变化都将触发所有依赖组件渲染,产生不必要的渲染
目前的解决办法只能是拆分更细粒度的 store。 另外一个办法是,添加一个 get 方法,只有使用到的数据才渲染。 此外,还可以使用 hooks 来优化一下更新条件,略复杂。
目前的解决办法只能是拆分更细粒度的 store。 另外一个办法是,添加一个 get 方法,只有使用到的数据才渲染。 此外,还可以使用 hooks 来优化一下更新条件,略复杂。
可否通过像redux-connect那样的高阶组件来解决?
- 将这个部分逻辑统一交给高阶组件和useMemo(新暴露一个API)去处理
- 写法上可能需要转变, 不能直接在组件内useStore(这个API替换成connect)
function connect(Target, mapStateToProps) {
return () => {
const portionStore = mapStateToProps(useStore())
const dependency = Object.keys(portionStore).reduce((acc, key) => {
(acc as any).push(portionStore[key])
return acc;
}, [])
return useMemo(() => <Target {...portionStore}/>, dependency)
}
}
createStore({
namespace: 'moduleA',
state: {
count: 0,
asyncData: '',
test: 'moduleA其他的state'
},
addCount() {
this.state.count++
},
minusCount() {
this.state.count--
},
async fetch () {
const res = await Axios.get(TEST_API_PATH);
this.state.asyncData = res.data.test
}
})
function child(props) {
console.log('子组件render')
return (
<div>
<span>{props.count}</span>
<span>{props.asyncData || '暂无'}</span>
<br/>
<Button onClick={() => {props.addCount()}}>+</Button>
<Button onClick={() => {props.minusCount()}}>-</Button>
<Button
onClick={() => props.fetch()}
loading={props.loading}
type="primary"
>
async
</Button>
</div>
)
}
const Child = connect(child, ({moduleA}) => ({
count: moduleA.state.count,
addCount: moduleA.addCount,
minusCount: moduleA.minusCount,
fetch: moduleA.fetch,
loading: moduleA.fetch.loading,
asyncData: moduleA.state.asyncData,
}));
function Parent(props) {
console.log('父组件render')
return (
<div>
<h2>父组件</h2>
<div>{props.test}</div>
<hr/>
<h2>子组件</h2>
<Child />
</div>
)
}
export default connect(Parent, ({moduleA}) => ({
test: moduleA.state.test
}));
谢谢你的建议。用高阶组件的话,和拆分store 感觉没什么太大区别。 当然在优化思路上都是只订阅必要的数据,必要时再更新。 目前可以参考的vue,还有另外一个响应式的蛮有名的库忘记叫什么了。不好意思想不起来,有段时间没接触这块。 这个库会更新,只是可能会比较慢。我自己在实际项目中一直在使用,只是没有通过npm而是直接拷贝的源码,有需要时就直接修改了