如何实现selector精准渲染

组件只在自己的数据变化时候render
举例
如果group变化了,不应该渲染用到了user的组件
//redux.jsx
在state里添加group

  1. const store = {
  2. state: {
  3. user:{name: 'frank',age: 18}
  4. group: {name: '前端组'}
  5. },

在幺儿子里添加connect,拿到group信息

  1. const 幺儿子 = connect(state => {
  2. return {group: state.group}
  3. })((group) => {
  4. return <section>幺儿子<div>Group: {group.name} </div> </section>
  5. })

顺利拿到group.name
image.png
问题他来了
修改二儿子input,幺儿子也执行
image.png
怎么解决问题
如果group没有更新,就不去渲染幺儿子
但是存在逻辑悖论,幺儿子执行才能做检查

回到connect,
image.png
在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时候,更新两次,幺儿子不会变化
image.png