React で <head>
の情報を書き換えるのに react-helmet を使った所 Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code.
という警告が発生してしまいました。
環境
- "react": "^17.0.2",
- "react-helmet": "^6.1.0"
react-helmet で発生した警告
import { VFC } from 'react'; import { Helmet } from 'react-helmet'; export const App: VFC = () => { return ( <> <Helmet> <title>{PAGE_TITLE}</title> <script src={SCRIPT} /> </Helmet> <div className="app">{/*略*/}</div> </> ); };
👇
Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code. See https://fb.me/react-unsafe-component-lifecycles for details. * Move code with side effects to componentDidMount, and set initial state in the constructor. Please update the following components: SideEffect(NullComponent)
React 16.3 以降 componentWillMount メソッドは安全でないとして非推奨になっていた
- 16.3: Introduce aliases for the unsafe lifecycles,
UNSAFE_componentWillMount
,UNSAFE_componentWillReceiveProps
, andUNSAFE_componentWillUpdate
. (Both the old lifecycle names and the new aliases will work in this release.)- A future 16.x release: Enable deprecation warning for
componentWillMount
,componentWillReceiveProps
, andcomponentWillUpdate
. (Both the old lifecycle names and the new aliases will work in this release, but the old names will log a DEV-mode warning.)- 17.0: Remove
componentWillMount
,componentWillReceiveProps
, andcomponentWillUpdate
. (Only the new “UNSAFE_” lifecycle names will work from this point forward.)Here, “unsafe” refers not to security but instead conveys that code using these lifecycles will be more likely to have bugs in future versions of React, especially once async rendering is enabled.
cf. Update on Async Rendering – React Blog
componentWillMount
, componentWillReceiveProps
, componentWillUpdate
は特に非同期レンダリングをするようになると誤用するとバグを発生させやすいので非推奨として、UNSAFE_
の付いたメソッドのエイリアスを作成し React v 17.0 で元のメソッドが削除となっているようです。
react-helmet では内部で使用しているライブラリ(react-side-effect
)で UNSAFE_componentWillMount
が使われているために、今回の警告が発生しているようでした。
cf. Stop using `UNSAFE_componentWillMount` · Issue #548 · nfl/react-helmet · GitHub
<head>
の変更は react-helmet-async を使う
react-helmet
relies onreact-side-effect
, which is not thread-safe. If you are doing anything asynchronous on the server, you need Helmet to encapsulate data on a per-request basis, this package does just that.
cf. react-helmet-async - npm
React Helmet を fork して作られた react-helmet-async はこの react-side-effect
の問題を解決しているようです。そして react-helmet-async は TypeScript なので @types
をインストールする必要もなく、Next.js でも使われているようです!(Download数も react-helmet-async の方が多いですね)
react-helmet-async の使い方
react-helmet-async は react-helmet とは少し異なり <Helmet>
タグを使用するコンポーネントを <HelmetProvider>
で囲ってあげる必要があります。
先ほど警告の出ていたコードを修正します。
import { VFC } from 'react'; + import { Helmet, HelmetProvider } from 'react-helmet-async'; - import { Helmet } from 'react-helmet'; export const App: VFC = () => { return ( + <HelmetProvider> - <> <Helmet> <title>{PAGE_TITLE}</title> <script src={SCRIPT} /> </Helmet> <div className="app">{/*略*/}</div> + </HelmetProvider> - </> ); };
これで Warning: Using UNSAFE_componentWillMount in strict mode is not recommended and may indicate bugs in your code.
な警告は出なくなりました!
アプリ全体で使うなら src/index.tsx
やアプリのルートになる src/App.tsx
でアプリを丸っと囲ってあげれば良さそう。
結論
React で <head>
を書き換えるときは react-helmet-async
を使おう!
Class Component 時代を通ってこなかったので componentWillMount
まわりのアレコレ全然把握してなかったのと、これからも React はどんどん変化していくだろうからちゃんとキャッチアップしておかないとな〜と感じました。
[参考]
イタリア映画おもしろいです!