(メモ) React.jsの<React.StrictMode>を知らなかった
ことわり
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で使ってました
import { WebSocketDemo } from './components/WebSocket';
import './App.css';
export const App = () => {
return (
<div className="App">
<h1> Chat </h1>
<WebSocketDemo />
</div>
);
}
react-use-websocketのサンプルをコンポーネントにしてちょっといじったやつです
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はたまに嘘言うと聞くし、これでは納得できないということで公式ドキュメントをみにいく
そもそも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を修正する
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