Reputation: 794
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?
Upvotes: 0
Views: 849
Reputation: 131
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>
}
Upvotes: 0
Reputation: 1984
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);
Upvotes: 0
Reputation: 984
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?
Upvotes: 0
Reputation: 378
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.
Upvotes: 0