![Reactで再レンダリングを考えずにコンポーネントを作成してはいけない](https://iwb.jp/wp-content/uploads/2024/05/dont-create-components-in-react-without-considering-re-rendering.png)
コンポーネント作成時は再レンダリングを考える
Reactを使用しているWebサイトで、たまにReactで再レンダリングを考慮せずにコンポーネントを作成されているケースがある。
例えば以下のコードの場合は、No.1, No.2, No.3で表示されず、 再レンダリングでNo.2, No.4, No.6と表示されます。(React.StrictModeの場合)
TSX
let num = 0
function Order() {
num = num + 1
return <h1>No.{num}</h1>
}
export default function App() {
return (
<>
<Order />
<Order />
<Order />
</>
)
}
![React 実行結果](https://iwb.jp/wp-content/uploads/2024/05/dont-create-components-in-react-without-considering-re-rendering-sample.png)
これを防ぐには、コンポーネントにpropsを渡して、再レンダリングで値が変わらないようにします。
TSX
type OrderProps = {
num: number
}
function Order({ num }: OrderProps) {
return <h1>No.{num}</h1>
}
export default function App() {
return (
<>
<Order num={1} />
<Order num={2} />
<Order num={3} />
</>
);
}
forでループ処理する場合は配列にpushして格納したものをreturnします。
TSX
type OrderProps = {
num: number
}
function Order({ num }: OrderProps) {
return <h1>No.{num}</h1>
}
export default function App() {
const orders = []
for (let i = 1; i <= 99; i++) {
orders.push(<Order key={i} num={i} />)
}
return orders
}
コード量が増えますが、<Order /> にnumなどの属性を付けないでnumを増やしたい場合はuseState, useEffect, useRefを利用すれば実装できます。
TSX
import { useState, useEffect, useRef } from 'react'
let globalNum = 0
const Order = () => {
const [num, setNum] = useState(0)
const isFirstRender = useRef(true)
useEffect(() => {
if (isFirstRender.current) {
globalNum++
setNum(globalNum)
isFirstRender.current = false
}
}, [])
return <h1>No.{num}</h1>
}
export default function App() {
return (
<div>
<Order />
<Order />
<Order />
</div>
)
}
React初心者やReact.StrictModeを使用していない環境だと、再レンダリングを考慮しないミスは結構多いので、Reactでコンポーネントを作成する際は注意が必要です。