はじめに
2022年3月29日に、React のバージョン 18 がリリースされましたね。
弊社でも6月からReact新機能勉強会が開始されたので、今回は予習を兼ねて勉強会の範囲内から物によって範囲外のものについてもまとめていこうかなと思います!
今回はStrictModeの挙動がReact18にバージョンアップした際に変更されたので説明していきます。
そもそもStrictモードとは?
以下MDNから引用
JavaScript のStrictは、 JavaScript の制限された変化形を利用する方法であり、それによって暗黙的に "sloppy mode" をやめることができます。厳格モードは単なるサブセットではありません。通常のコードとは意図的に異なる意味を持っています。
端的にいうとjavascriptのコードを通常より厳しくエラーチェックすることのできる仕組みのことです。
メリットとして
- 将来の ECMAScript で予定されている構文(キーワードを変数名として使用するなど) を禁止して、バージョンが変わった後の動作を修正を無くことができる。
- Javascriptの構文としてはエラーにはならないが、バグを誘発するようなコードを検出することができる
などがあげられます。
React18でのStrictモードの新たな挙動
以下React公式より引用
将来的に、React が state を保ったままで UI の一部分を追加・削除できるような機能を導入したいと考えています。
この機能により、React の標準状態でのパフォーマンスが向上しますが、コンポーネントは副作用が何度も登録されたり破棄されたりすることに対して耐性を持つことが必要になります。ほとんどの副作用は何の変更もなく動作しますが、一部の副作用は一度しか登録・破棄されないものと想定しています。
この問題に気付きやすくするために、React 18 は strict モードに新しい開発時専用のチェックを導入します。この新しいチェックは、コンポーネントが初めてマウントされるたびに、すべてのコンポーネントを自動的にアンマウント・再マウントし、かつ 2 回目のマウントで以前の state を復元します。
パッと見てわかる方なら 「完全に理解した!」 となるかも知れませんが、自分は頭の中でスッキリしなかったので実コードを用いて検証してみました。
今回はReact17
とReact18
のコードを使用して動作の方を見ていきましょう!
React17の挙動
以下の記事を見ながらReact17の環境構築をしてください!
環境構築が終わったら以下のコードをsrc/App.tsx
に記述してください。
import { useEffect } from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
console.log('App rendered!')
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
上記のスクリーンショットで分かるように、Appコンポーネントが1度だけレンダリングされていることが分かると思います!
React18の挙動
同様のコードをsrc/App.tsx
に記述してください。
そうすると...
App rendaring!
という文章が2回出力されており、2回App
コンポーネントが
レンダリングされているのがわかると思います。
このような形でReact18では、コンポーネントが表示された瞬間にそれを1度破棄して、
またすぐ表示するみたいなことを裏側で行うような動きをしています。
なぜ、このような一見無駄な動きをしているのかというと今後のReactの機能追加を想定しているためです。
具体的にいうと、オフスクリーン(offscreen)
という機能が追加されると言われています。
タブ遷移のように画面からは1度遷移させてまた元の画面に戻って状態を復活させたりなど、
ユーザーが高速に表示させる際にその時の状態をステートを復元させることでよりユーザーに高速
にアプリを使ってもらえるような仕組みが提供されようとしています。
上記で説明したオフスクリーン(offsereen)
でアプリが再マウントされるような動きになってしまうため、
React18のStricモードでは2回レンダリングされる仕様となっております。
Strictモードをオフにしたい際は...?
src/index.tsx
を下記の部分を削除してください。
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
root.render(
- <React.StrictMode>
<App />
- </React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
そうすると、React17以前同様に1度だけレンダリングされます。
また、Stricモードに関しては開発環境のみ適用されるもので
本番環境では1回のレンダリングの動きしかしないことを覚えておいてください!
最後に
なるべく、Strictモードをオンにしてアプリをアンマント・再マウントしても
開発環境で不具合が起きないような作り方をしていくのが今後のReactにおいての開発に
重要になっていくのかなと思います。
今回の内容のウケが良ければ、またReact18の新機能関連の記事について
投稿していこうかなと思います!
本記事がReact18を学習している方の参考になれば嬉しいです!