🙄

(メモ) React.jsの<React.StrictMode>を知らなかった

2023/05/23に公開

ことわり

TypeScriptもReactも超初心者でコピペです。書き方は勘弁してください🙇

結論

  • 公式ドキュメントをみておこう
  • <React.StrictMode>を使うとレンダリングが多く走ってhookも影響を受ける

環境

OS : Mac
Node : v16.13.0
React : ^v18.2.0

起こったこと

ファイルの様子

create-react-appをしてすぐのディレクトリ構成です

src
├── App.css
├── App.test.tsx
├── App.tsx
├── components
│   └── WebSocket.tsx
├── index.css
├── index.tsx
├── logo.svg
├── react-app-env.d.ts
├── reportWebVitals.ts
└── setupTests.ts

hookを含んだコンポーネントをApp.tsxで使ってました

App.tsx
import { WebSocketDemo } from './components/WebSocket';
import './App.css';

export const App = () => {
  return (
    <div className="App">
      <h1> Chat </h1>
      <WebSocketDemo />
    </div>
  );
}

react-use-websocketのサンプルをコンポーネントにしてちょっといじったやつです

WebSocket.tsx
import { useState, useCallback, useEffect } from 'react';
import useWebSocket, { ReadyState } from 'react-use-websocket';

export const WebSocketDemo = () => {

const [socketUrl, setSocketUrl] = useState('ws://localhost:8000');
        
const [messageHistory, setMessageHistory] = useState<MessageEvent[]>([]);

const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl);

useEffect(() => {
    if (lastMessage !== null) {
        setMessageHistory((prev) => prev.concat(lastMessage));
    }
}, [lastMessage]);

const handleClickSendMessage = useCallback(() => sendMessage('Hello'), []);

const connectionStatus = {
    [ReadyState.CONNECTING]: 'Connecting',
    [ReadyState.OPEN]: 'Open',
    [ReadyState.CLOSING]: 'Closing',
    [ReadyState.CLOSED]: 'Closed',
    [ReadyState.UNINSTANTIATED]: 'Uninstantiated',
}[readyState];

return (
        <div>
            <button
                onClick={handleClickSendMessage}
                disabled={readyState !== ReadyState.OPEN}
            >
                Click Me to send 'Hello'
            </button>
            <p>The WebSocket is currently : {connectionStatus}</p>
            {lastMessage ? <h2>chat start</h2> : <h2>chat stop.</h2>}
            <ul>
            {messageHistory.map((message, idx) => (
                <p key={idx}>{message ? message.data : null}</p>
            ))}
            </ul>
        </div>
    );
};

これを動かしてみたらなぜかコネクションが二重に走ってた

調査

最初はサーバー側が悪いと思っていた。全然うまくいかず最終的にコードをChatGPTさんに見せてみた

本当か? ChatGPTはたまに嘘言うと聞くし、これでは納得できないということで公式ドキュメントをみにいく

https://react.dev/reference/react/StrictMode
※ 知らないうちに公式ドキュメントがかっこよくなってた
そもそもStrictModeは開発中に使う問題点をあらかじめ洗い出してれるものだそう

気になる記述を見つけたので読む

Strict Mode enables the following development-only behaviors:
・Your components will re-render an extra time to find bugs caused by impure rendering.
・Your components will re-run Effects an extra time to find bugs caused by missing Effect cleanup.
・Your components will be checked for usage of deprecated APIs.

Your components will re-render an extra time to find bugs caused by impure rendering.

意訳:バグを見つけるためにレンダリングを行う
なるほどな。レンダリングが余分に走ってそれに引っ張られてhookも反応したのかも?

index.tsxを修正する

index.tsx
import React from 'react';
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();

コネクションが1回になった

ひとまず

今は解決とする
hookはまだまだ全然わからないのでこれから勉強していく。

Discussion