Проблема 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);
Другие вопросы по тегам