Проблема React.memo с Redux
У меня две составляющие.
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
});
Моя проблема в том, что где-то меняют stateA, нажимая на
Child
сохранит предыдущее состояние A. Я не могу получить доступ к последнему состоянию А.
Вы видите, я не хочу
Child
повторный рендеринг при изменении состояния A, он должен повторно отображаться только при изменении состояния B. Но я хочу получить доступ к последнему состоянию А в
Parent
при нажатии на
Child
.
Есть ли способ решить эту проблему?
4 ответа
Вы должны иметь доступ
props.stateA
без проблем
const handleClick = () => {
console.log(props.stateA);
};
потому что вы получаете доступ к родительскому реквизиту в
handleClick
. Так что если
props.stateA
устарело, то логический вывод - родитель не получает последние реквизиты. Можем ли мы увидеть, как вы обновляете реквизиты / состояние?
Если
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>
Надеюсь, это сработает для вас.
Вы можете сохранить
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>
}
Проблема, с которой вы столкнулись, не имеет ничего общего с Redux.
Родительский компонент передает 2 реквизита дочернему элементу: текст, который изменяется при необходимости и который изменяется при каждом рендеринге родительского компонента — каждый раз создается новая функция.
Но React.memo проверяет только text prop, поэтому дочерний элемент довольно часто получает stale.
Правильное решение - завернуть
handleClick
с помощью useCallback и проверьте все реквизиты в
React.memo
(реакция делает это по умолчанию).
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);