😊
今更ながらReact17 → React18でつまづいた所
株式会社イルシルCTO 倉橋康熙です。
業務でReact17→React18のアップデートを行ったので備忘録に。
1. useHistoryは使えない
useHistoryは廃止されてしまったのでhistory.pushやhistory.replace、hisotry.location.pathname等は全て使えません。
useNavigation、useLocationを使いましょう
// react-douter-dom v5
const history = useHistory();
history.push("/")
history.replace("/")
history.location.pathname
<Redirect to="/"/>
// react-douter-dom v6
const navigation = useNavigate();
const location = useLocation()
navigation("/")
navigation("/", { replace: true })
location.pathname
<Navigate replace to="/"/>
2. useEffectの返り値や非同期に気をつける
React18へアップデートする際
TypeError: destroy is not a function
のように出ることがあります。
今回の場合は以下のようなuseEffectがあったからでした。
※頑張ってこのようにuseEffect使用してる箇所全部探しましょう
// useEffectの第一引数自体が非同期関数になってしまっている
useEffect(async() => {
...
})
// useEffectの返り値がundefinedか関数のどちらでもない場合
useEffect(() => {
...
return someValue;
})
3. ルーティングの入れ子構造
以前までは以下のような形でルーティングしている部分がありました。
const RouteComponent = () => {
...
return (
<BrowserRouter>
<Switch>
...
<Route path="*">
<SomeComponent />
</Route>
</Swich>
</BrowserRouter>
)
}
const SomeComponent = () => {
...
return (
<Switch>
<Route ...
</Swich>
)
}
しかしreact-router-dom v6ではそのままでは入れ子構造にできずにuseLocationの返り値を渡す必要がありました。
const RouteComponent = () => {
...
return (
<BrowserRouter>
<Routes>
...
<Route path="*" element={ <SomeComponent />} />
</Swich>
</BrowserRouter>
)
}
const SomeComponent = () => {
...
const location = useLocation()
return (
<Routes location={location}>
<Route ...
</Swich>
)
}
4. 循環参照にご注意を
特に心当たりがないのに以下のエラーが出る時は循環参照を疑いましょう。
ReferenceError: Cannot access 'XXX' before initialization
以上React18へのアップデートの際につまづいた点でした。
皆さんのご知見になればと思います🙇
Discussion