EY-Office ブログ

React開発環境ではなぜかコンポーネントが2回描画される、しかしconsole.logは1回しか表示されない

Reactのコンポーネントの描画(render、表示)はReactライブラリーが制御していて、Reactに不慣れなプログラマーには思わぬタイミングで描画される事があります。

しかしReactで描画が行われるのは以下の場合です

  1. React(JavaScript)のコードがブラウザーに読み込まれた直後
  2. コンポーネントの引数(props)が変わったとき
  3. コンポーネントの管理する状態(ステータス、state)が変わったとき
  4. Contextを参照しているコンポーネントで、Contextの値が変わったとき

React教育を行っているとReactに不慣れな受講者は、ときどき不思議なコードを書いてくれます。

以下のコードを実行すると、描画が起きるのは1.のみで、ブラウザーの画面にはcount = 1と表示されるように思えます。
(このコードはReactの設計思想からすると望ましくないコードですが、初心者は書いてしまいがちなコードです)

import React from 'react'

let count = 0

export const App: React.FC = () => {
  count++
  console.log(`count: ${count}`)
  return  (<div>count = {count}</div>)
}

しかし、なぜか以下のようにcount = 2と表示されます!
環境は最新のcreate-react-app(react: 17.0.1, react-scripts: 4.0.1, typescript: 4.0.5, node.js: 14.15.0)で作った環境です。

React開発環境の怪

プロダクション用コードで試す

npm run buildで、プロダクション(本番)用コードを生成し、それをnginxで動かすと下の画像のようにcount = 1と表示されます。論理的にあっています 😀

React開発環境の怪

開発環境ではコンポーネントが2回描画されている

下のようにconsole.log()の後ろにalert()を追加して実行してみました。

import React from 'react'

let count = 0

export const App: React.FC = () => {
  count++
  console.log(`count: ${count}`)
  alert(`count: ${count}`)
  return  (<div>count = {count}</div>)
}

alertは2回表示されます、しかもalertに表示されるcountの値も思った通りの値です。しかし、console.logには1しか表示されていません。

React開発環境の怪

React開発環境の怪

今日の結論

ここまでの結論は、

  • create-react-appで作った開発環境では、コンポーネントが2回描画(実行)される場合がある
    • これはコードの変更が直ぐに画面に反映される、ホットリロードに関係するのでしょうか?
  • しかし、console.logは1回しか表示されない
  • この現象はプロダクション環境では起きない
  • Reactの設計思想にそったコードなら、2回描画されても問題は起きない

原因は開発環境で使われているコードを読んでみないと判らないと思います、
初心者は思わぬコードを書きます😀 そこからシステムの深淵が顔を覗かせたようですね。

- about -

EY-Office代表取締役
・プログラマー
吉田裕美の
開発者向けブログ