我有两个组件。
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
});
我的问题是,当状态A在某个地方更改时,单击Child
将记录以前的状态A。我无法访问最新的stateA。
你可以看到,当状态A改变时,我不想Child
重新渲染,它应该只在状态B改变时重新渲染。但我想在单击Child
时访问Parent
中的最新状态A。
有什么方法可以解决这个问题吗?
如果Parent
组件是功能组件,那么您可以像这样使用
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>
我希望它对你有用。
您应该能够访问props.stateA
,没有问题的
const handleClick = () => {
console.log(props.stateA);
};
因为你在handleClick
中访问了父母的道具。因此,如果props.stateA
过时,那么逻辑结论是父级没有收到最新的道具。我们可以看看你是如何更新道具/状态的吗?
您遇到的问题与Redux无关。
Parent组件将两个道具传递给子级:在需要时更改的文本和在Parent组件的每个渲染中更改的handleClick
-每次都会创建一个新函数。
但是React.memo只检查文本道具,所以孩子经常收到一个过时的handleClick
。
正确的解决方案是用useCallback包装handleClick
,并检查React.memo
中的所有道具(默认情况下react会这样做(。
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);
您可以保留一个ref
到stateA
,这样它就是调用handleClick
时记录的内容。useRef
确保使用最后一个值。
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>
}