简体   繁体   中英

React.memo issue with Redux

I have two components.

function Parent(props){

  const handleClick = () => {
   console.log(props.stateA);
  };

  return <div><Child text={stateB} handleClick={handleClick} /></div>
}

const mapStateToProps = (state) => {
  return {
    stateA: state.stateA // stateA will be changed somewhere else
    stateB: state.stateB
  }
};

export default connect(mapStateToProps)(Parent);
function Child(props) {
   return <div onClick={props.handleClick}>{props.text}</div>
}

export default React.memo(Child,(prev, next) => {
   return prev.text === next.text
});

My problem is when stateA is changed somewhere, clicking on Child will log the previous stateA. I can't access the latest stateA.

You can see, I don't want to Child re-render when stateA changes,it should re-render only when stateB changed. But I want to access the latest stateA in Parent when clicking on Child .

Is there any method to solve this problem?

If the Parent component is a functional component then you can use like this

 const [valueA, setValueA] = useState('')
 useEffect(() => {
      setValueA(props.stateA)
 },[props.stateA])

 console.log(valueA) // latest Value of stateA
 return <div><Child text={stateB} handleClick={handleClick} /></div>

I hope it'll work for you.

You should be able to access props.stateA no problem

const handleClick = () => {
   console.log(props.stateA);
};

because you accessing parent's props in handleClick . So if props.stateA is stale then the logical conclusion is the parent doesn't receive the latest props. Can we see how you update props/state?

You can keep a ref to stateA so it is what is logged when you call handleClick . useRef ensures that the last value is used.

function Parent(props){
  const stateARef = useRef(props.stateA);

  useEffect(() => {
    stateARef.current = props.stateA;
  }, [props.stateA])

  const handleClick = () => {
   console.log(stateARef.current);
  };

  return <div><Child text={stateB} handleClick={handleClick} /></div>
}

The problem you are experiencing has nothing to do with Redux.

The Parent component passes 2 props to the child: the text which is changed when needed and handleClick which is changed each render of the Parent component - a new function is created each time.

But the React.memo is checking only the text prop, so the child receives a stale handleClick quite often.

The correct solution is to wrap the handleClick with useCallback and check all props in React.memo ( react does this by default).

function Parent(props){

  const handleClick = useCallback(() => {
   console.log(props.stateA);
  }, []);

  return <div><Child text={stateB} handleClick={handleClick} /></div>
}

const mapStateToProps = (state) => {
  return {
    stateA: state.stateA // stateA will be changed somewhere else
    stateB: state.stateB
  }
};

export default connect(mapStateToProps)(Parent);

function Child(props) {
   return <div onClick={props.handleClick}>{props.text}</div>
}

export default React.memo(Child);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM