Я пытался сделать то же самое с хуком useEffect, но кажется, что в возвращаемой функции useEffect состояние неверно.
Причина этого заключается в замыканиях.Замыкание - это ссылка функции на переменные в своей области видимости.Ваш useEffect
обратный вызов запускается только один раз, когда компонент монтируется, и, следовательно, обратный обратный вызов ссылается на начальное значение счетчика 0.
Ответы, приведенные здесь, являются тем, что я бы порекомендовал.Я бы порекомендовал ответ @Jed Richard о передаче [count]
в useEffect
, что дает запись в localStorage
только при изменении количества.Это лучше, чем подход, не пропускающий вообще ничего при каждом обновлении.Если вы не меняете счетчик слишком часто (каждые несколько мс), вы не заметите проблем с производительностью, и можно писать в localStorage
всякий раз, когда меняется count
.
useEffect(() => { ... }, [count]);
Если вы настаиваете только назаписывая localStorage
о размонтировании, вы можете использовать некрасивый хак / решение - refs.По сути, вы бы создали переменную, которая присутствует на протяжении всего жизненного цикла компонента, на которую вы можете ссылаться из любого места внутри него.Однако вам придется вручную синхронизировать ваше состояние с этим значением, и это очень хлопотно.Ссылки не дают вам упомянутой выше проблемы закрытия, потому что ссылка - это объект с полем current
, и множественные вызовы useRef
вернут вам один и тот же объект.Пока вы изменяете значение .current
, ваш useEffect
всегда может (только) читать самое последнее значение.
Ссылка CodeSandbox
const {useState, useEffect, useRef} = React;
function Example() {
const [tab, setTab] = useState(0);
return (
<div>
{tab === 0 && <Content onClose={() => setTab(1)} />}
{tab === 1 && <div>Count in console is not always 0</div>}
</div>
);
}
function Content(props) {
const value = useRef(0);
const [count, setCount] = useState(value.current);
useEffect(() => {
return () => {
console.log('count:', value.current);
};
}, []);
return (
<div>
<p>Day: {count}</p>
<button
onClick={() => {
value.current -= 1;
setCount(value.current);
}}
>
-1
</button>
<button
onClick={() => {
value.current += 1;
setCount(value.current);
}}
>
+1
</button>
<button onClick={() => props.onClose()}>close</button>
</div>
);
}
ReactDOM.render(<Example />, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>
<div id="app"></div>