React usePrevious, похоже, не имеет предыдущего значения

#reactjs #react-hooks #use-effect

Вопрос:

В своих функциональных компонентах React я пытаюсь использовать пользовательский usePrevious для получения/сравнения предыдущего значения моего объекта контекста. Однако, похоже, что он всегда имеет последнее значение, а не предыдущее значение. Ниже приведен мой код. Пожалуйста, дайте мне знать, если я делаю здесь что-то не так.

 function MyHeaderComponent(props) {
    const [myPref, setMyPref] = React.useContext(MyContext);
    const prevPreferences = usePrevious(myPref.preferences);
    
    useEffect(() => {
        console.log("prevPreferences : "   prevPreferences);        // Prints current context object, instead of the previous one
        // I want to call myInfo only if prevPreferences is not the same as myPref.preferences (i.e. current)
    }, [myPref]);
        
    function usePrevious(value) {
        const ref = useRef();
        useEffect(() => {
            ref.current = value;
        });
        return ref.current;
    }    

    const myInfo = async () => {
        setMyPref(myPref);
    }

    return (
        <>
            <div>
                Some JSX
            </div>
        </>
    )
}


export default withRouter(withStyles()(MyHeaderComponent));


function MyPreferences(props) {
    const [myPref, setMyPref] = React.useContext(MyContext);
    
    // somewhere in code
    setMyPref(myPref);                
}
 

Комментарии:

1. Почему этот пользовательский крючок определен внутри компонента? Каждый раз вы получаете совершенно новый крючок, который вряд ли поможет сохранить какую-либо историю.

2. Я попытался воспроизвести его. Я не мог codesandbox.io/s/boring-cray-z628s?file=/src/App.js . Пожалуйста, предоставьте свой минимальный воспроизводимый образец.

3. @jonrsharpe — Даже после создания отдельного файла/крючка я сталкиваюсь с той же проблемой…

Ответ №1:

Эта реализация useLatest (которая, кстати, не должна находиться внутри компонента) не копирует значение в поле ссылки, она просто присваивает ссылку.

Я бы поспорил myPref.preferences , что он будет внутренне изменен (вместо того, чтобы быть переназначенным новому объекту), поэтому вы всегда видите одно и то же значение.

Комментарии:

1. Значит, нет никакого способа получить старое значение ?

2. Либо сделайте так, чтобы ваш useLatest крючок скопировал значение (например, Lodash cloneDeep ), либо убедитесь, что вы всегда присваиваете ему новое значение и не изменяете его внутренне.

Ответ №2:

Я думаю, проблема в том, что вы используете хук usePrevious внутри другого функционального компонента. Не могли бы вы попробовать создать файл для крючка usePrevious.

usePreviousState.js

 function usePrevious(value, initialValue) {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  if (ref.current === undefined amp;amp; initialValue !== undefined) {
    return initialValue;
  }
  return ref.current;
}
 

Комментарии:

1. Спасибо… пробовал это…. та же проблема…