useEffect を「マウント時の処理」と捉えるべきでない -- 「マウント時の初期化処理」はきわめて例外的
例外1: useState の初期値・initializer関数(初期化関数)を使った初期化
参考記事: 【React】誤解される useMemo と 誤用される useState ―― 「A の変更に反応して B の値が変わる」と考えるべきでない
https://qiita.com/honey32/items/58e56e407d4d87e294a4
初期値の固定
https://zenn.dev/yumemi_inc/articles/react-initial-state-take-advantage
code:tsx
const TaskEditForm: FC<Props> = ({ defaultValues }) => {
const values, setValues = useState<TaskEditFormValues>(defaultValues);
// 以下略
(レンダリング結果を左右しなければ)初期化関数でアレコレできる
例: https://tanstack.com/query/v4/docs/react/eslint/stable-query-client
code:tsx
function App() {
const queryClient = useState(() => new QueryClient())
return (
<QueryClientProvider client={queryClient}>
<Home />
</QueryClientProvider>
)
}
例外2: useSyncExternalStore を使った、SSR セーフな初期化処理
Hydration mismatch回避にuseEffectを使うな by sssota さん
https://qiita.com/ssssota/items/51278dc5d51801dfb3fc
エフェクトは「マウント時の初期化処理」を書くものではない
「マウント時」 +「更新時」を一体のものとして捉えるのがエフェクト
「レンダリングのたびに、補足されたリアクティブ値が変われば、それに応じて再実行するもの」と捉えるべき
https://zenn.dev/yumemi_inc/articles/react-effect-simply-explained
本当に欲しかったのは「当該ステートが初期状態のとき、実行しない」では?
…というXY 問題
【useEffect】《初回には実行しない》は不可能だけど《ステートを見て実行中止する》は可能です
https://qiita.com/honey32/items/f8f12afa1bd69e714e40
code:typescript
const roomId, setRoomId = useState("");
useEffect(() => {
if (!roomId) return;
const disconnect = connectToChat(roomId);
return () => {
disconnect();
}
}, roomId);