如何实现selector精准渲染
组件只在自己的数据变化时候render
举例
如果group变化了,不应该渲染用到了user的组件
//redux.jsx
在state里添加group
const store = {state: {user:{name: 'frank',age: 18}group: {name: '前端组'}},
在幺儿子里添加connect,拿到group信息
const 幺儿子 = connect(state => {return {group: state.group}})((group) => {return <section>幺儿子<div>Group: {group.name} </div> </section>})
顺利拿到group.name
问题他来了
修改二儿子input,幺儿子也执行
怎么解决问题
如果group没有更新,就不去渲染幺儿子
但是存在逻辑悖论,幺儿子执行才能做检查
回到connect,
在wrapper里面做检查
如果data没有改变,那不去渲染
export const connect = (selector) => (Component) => {
return (props) => {
const { state,setState } = useContext(appContext)
const [, update] = useState({})
const data = selector ? selector(state) : {state: state}
useEffect(() => {
store.subscribe(() => {
//得到新的data
const newData = selector ? selector(store.state) : { state: store.state};
//对比变化
if(changed(data, newData)) {
console.log('update')
//update
update({})
}
})
//useEffect用到了哪些来自属性的东西,都要写在依赖里面
//最好取消订阅,否则 再selector变化时候出现重复订阅
}, [selector])
const dispatch = (action ) => {...}
return <Component {...props} {...data} dispatch={dispatch}/ >
export const appContext = React.createContext(null)
添加了什么
之前的代码是如果store变化了,直接update
现在添加了2句
先看一眼新数据是什么newData
然后看newData和data是否变化了
newData得到的过程和data是一致的
newData是在订阅发生变化后得到的新statestore.subscribe(() => {
新数据和旧数据有没有变化
声明函数changed,做一个遍历
一旦属性变化了就需要更新
const changed = (oldState,newState) => {
let changed = false;
for (let key in oldState ) {
if(oldState[key] !== newState[key]) {
changed = true;
}
}
return changed
}
取消订阅
返回return subscribe
useEffect(() => {
return store.subscribe(() => {
//得到新的data
const newData = selector ? selector(store.state) : { state: store.state};
//对比变化
if(changed(data, newData)) {
console.log('update')
//update
update({})
}
})
改写
useEffect(() => store.subscribe(() => {
const newData = selector ? selector(store.state) : { state: store.state};
if(changed(data, newData)) {
update({})
}
}),[selector])
最终效果
当发现数据不一样,就去update,如果selector更新了,就取消之前的订阅,来开启一个新的订阅
input时候,更新两次,幺儿子不会变化
