🐷
ReactのuseMemoについてのコンポーネント考察メモ
useMemoはどれぐらいコンポーネントのRe-evaluateを避けるかについての考察です
useMemoは、必要の時だけコンポーネントのRe-evaluateを行う、というhookです
まずはuseMemoなしのサンプルです
コンポーネント構成はこちらです
コードはこちらです(ButtonはUIなので省略します)
App.js
function App() {
const [showParagraph, setShowParagraph] = useState(false);
console.log('APP RUNNING');
function toggleParagraphHandler() {
setShowParagraph((prevShowParagraph) => !prevShowParagraph);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Output show={showParagraph} />
<Button onClick={toggleParagraphHandler}>Toggle Paragraph</Button>
</div>
);
}
Output.js
function Output(props) {
console.log('OUTPUT RUNNING');
return <Paragraph show={props.show} />
}
export default Output;
Paragraph.js
function Pharagraph(props) {
console.log('PARAGRAPH RUNNING');
return <p>{props.show && 'This is new'}</p>;
}
export default Paragraph;
Output.jsとParagraph.jsの間は、結構無駄ですが
今回の実験のために敢えてこのような構成を使います
そして、コードを起動してみると
ログをテキストしてみます
# 起動
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
# ボタンをクリック
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
# ボタンをクリック
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
ご覧の通り、毎回ボタンをクリックすると、関連あるコンポーネントは全部再起動したようです
(今回はButton.jsを省きますが、もしButton.jsにconsole.logを入れたら、Buttonのログも見れます)
ちなみに、props.show
を削除して、Paragraph.jsに固定のテキストを入れても
同じ量なログが飛んできますので
それは大変災難ですね
ここで、useMemo()
でどれぐらいログを軽減できるのかを検証してみます
useMemo
使います
そのままOutput.jsのexportにReact.Memoを入れます
(Paragraph.jsに入れなくていいです、もしOutputにRe-evaluateが行わなかったら、Paragraphにも発生しません)
Output.js
function Output(props) {
console.log('OUTPUT RUNNING');
return <Paragraph show={props.show} />
}
-export default Output;
+export default React.memo(Output);
検証結果は同じく
# 起動
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
# ボタンをクリック
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
# ボタンをクリック
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
show={false}
を使ってみる
つまり、ボタンを何回クリックしても
文字が表れないままになります
App.js
function App() {
const [showParagraph, setShowParagraph] = useState(false);
console.log('APP RUNNING');
function toggleParagraphHandler() {
setShowParagraph((prevShowParagraph) => !prevShowParagraph);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
- <Output show={showParagraph} />
+ <Output show={false} />
<Button onClick={toggleParagraphHandler}>Toggle Paragraph</Button>
</div>
);
}
Output.js
function Output(props) {
console.log('OUTPUT RUNNING');
return <Paragraph show={props.show} />
}
export default React.memo(Output);
Paragraph.js
function Pharagraph(props) {
console.log('PARAGRAPH RUNNING');
return <p>{props.show && 'This is new'}</p>;
}
export default React.memo(Paragraph);
検証結果は以下です
# 起動
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
# ボタンをクリック
APP RUNNING
# ボタンをクリック
APP RUNNING
すごく大量のログを減りましたが、画面が変わったからダメです
props.children
を使ってみる
<Output show={false} />
を<Output show={showParagraph} />
に戻り、続いて修正します
App.js
function App() {
const [showParagraph, setShowParagraph] = useState(false);
console.log('APP RUNNING');
function toggleParagraphHandler() {
setShowParagraph((prevShowParagraph) => !prevShowParagraph);
}
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Output show={showParagraph} />
<Button onClick={toggleParagraphHandler}>Toggle Paragraph</Button>
</div>
);
}
Output.js
function Output(props) {
console.log('OUTPUT RUNNING');
- return <Paragraph show={props.show} />
+ return <Paragraph>{props.show && 'This is new'}</Paragraph>;
}
export default React.memo(Output);
Paragraph.js
function Pharagraph(props) {
console.log('PARAGRAPH RUNNING');
- return <p>{props.show && 'This is new'}</p>;
+ return <p>{props.children}</p>;
}
export default React.memo(Paragraph);
ログは以下です
# 起動
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
# ボタンをクリック
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
# ボタンをクリック
APP RUNNING
DEMOOUTPUT RUNNING
PARAGRAPH RUNNING
Discussion