useEffectのreturn部分
前提:Reactで使われるuseEffectについて、第二引数に空配列[]
を設定すると、useEffect内の処理はコンポーネントマウント時、returnにコールバックを設定するとコンポーネントアンマウント時にそれぞれ一度だけ実行される。
useEffect(() => {
// コンポーネントマウント時に実行
return () => {
// コンポーネントアンマウント時に実行
};
}, []);
アンマウント時に実行したいコールバック内で、例えばuseStateでセットした値を使おうとすると、うまくいかなかった。例えば、こんな感じ。
const [str, setStr] = useState<string>('initial string');
...
useEffect(() => {
setStr('updated string');
return () => {
console.log(str); // initial string
};
}, []);
console.log(str); // updated string
useEffect外でのconsole.log()ではちゃんと'updated string'が出るのになぜだ...!?!?
setState()が非同期処理のためすぐにはセットされないことは知っていたのですが...
解決方法
const [str, setStr] = useState<string>('initial string');
...
useEffect(() => {
const outputString = 'updated string';
setStr(outputString);
return () => {
console.log(outputString); // updated string
};
}, []);
console.log(str); // updated string
returnのコールバックは、コールバックがセットされた時点での値を参照するようでした。
※ただの私の経験談なので実際は間違っている可能性があります
setState()は非同期であるためコールバックがセットされた時点ではまだstrに値が代入されていない可能性があります。
今回の実装ではsetState()するのはuseEffect()内だけだったので、
- outputStringに値を保持しておく
- setStr()する
- return文内ではstrではなく保持して置いた値(outputString)を使う
これで動きました。
じゃあ後から代入した値を使いたいときはどうするんだろう...という疑問は残りますが...
残ってしまった疑問
例えばuseEffect外で...というか、コンポーネントマウント後にsetStateした値をreturnのコールバック内で使う場合ってどうするんだろう...
const [str, setStr] = useState<string>('initial string');
useEffect(() => {
return () => {
console.log(outputString); // initial string 👈これを"updated string"にしたいときって...
};
}, []);
// useEffect外で
setStr("updated string");
わかったら追記します。