Skip to content

ReactにおけるABC問題

ReactにおけるABC問題とは

  • CのonClickイベントハンドラ内の処理を起点にしてBを再描画させる
  • Cは再描画させない
  • Reactが標準で提供しているAPIのみを使用する
  • コンポーネントのメモ化をしてはいけない
const A = () => {
return (
<div>
<p>This is A component.</p>
<B />
<C />
</div>
)
}
interface BProps {}
const B = () => {
// Bは再描画させたい
return (
<div>
<p>This is B component.</p>
</div>
)
}
interface CProps {}
const C = () => {
// Cは再描画させない
return (
<div>
<p>This is C component.</p>
<button
onClick={() => {
// ここの処理の中でBを再描画させたい
}}
>
Click
</button>
</div>
)
}

答え

useRefを使った一番シンプルな答えがこれ。

import { MutableRefObject, useRef, useState } from 'react'
const A = () => {
const setToggleRef = useRef<() => void>(() => {})
return (
<div>
<p>This is A component.</p>
<B setToggleRef={setToggleRef} />
<C setIsToggleRef={setToggleRef} />
</div>
)
}
interface BProps {
setToggleRef: MutableRefObject<() => void>
}
const B = ({ setToggleRef }: BProps) => {
const [toggle, setToggle] = useState(false)
setToggleRef.current = () => {
setToggle((current) => !current)
}
return (
<div>
<p>This is B component.</p>
<p>Toggle: {toggle ? 'true' : 'false'}</p>
</div>
)
}
interface CProps {
setIsToggleRef: MutableRefObject<() => void>
}
const C = ({ setIsToggleRef }: CProps) => {
return (
<div>
<p>This is C component.</p>
<button
onClick={() => {
setIsToggleRef.current()
}}
>
Click
</button>
</div>
)
}

参考

ちゃんとReactのドキュメント読もうね