useMemo
useMemo γ―γγ¬γ³γγΌιγ§θ¨οΏ½?οΏ½η΅ζγγγ£γγ·γ₯γγγγοΏ½? React γγγ―γ§γγ
const cachedValue = useMemo(calculateValue, dependencies)- γͺγγ‘γ¬γ³γΉ
- δ½Ώη¨ζ³
- γγ©γγ«γ·γ₯γΌγγ£γ³γ°
- εγ¬γ³γγΌοΏ½?γγ³γ«θ¨οΏ½?οΏ½γ 2 εοΏ½?οΏ½θ‘γγγ
useMemoοΏ½?θΏγε€γγγͺγγΈγ§γ―γγ§γ―γͺγ undefined γ«γͺγ£γ¦γγΎγ- γ³γ³γγΌγγ³γγγ¬γ³γγΌγγγγγ³γ«
useMemoε οΏ½?ι’ζ°γεοΏ½?οΏ½θ‘γγγ - γ«γΌγε
οΏ½?γͺγΉγοΏ½?ει
οΏ½?γ«γ€γγ¦
useMemoγεΌγ³εΊγγγγγη¦ζ’γγγ¦γγ
γͺγγ‘γ¬γ³γΉ
useMemo(calculateValue, dependencies)
γ³γ³γγΌγγ³γοΏ½?γγγγ¬γγ«γ§ useMemo γεΌγ³εΊγγ¦γγ¬γ³γγΌιγ§θ¨οΏ½?οΏ½γγγ£γγ·γ₯γγΎγγ
import { useMemo } from 'react';
function TodoList({ todos, tab }) {
const visibleTodos = useMemo(
() => filterTodos(todos, tab),
[todos, tab]
);
// ...
}εΌζ°
-
calculateValue: γγ£γγ·γ₯γγγε€γθ¨οΏ½?οΏ½γγι’ζ°γη΄ι’ζ°γ§γεΌζ°γεγγγδ»»ζοΏ½?εοΏ½?δ½γγοΏ½?ε€γθΏγεΏ θ¦γγγγΎγγReact γ―εεγ¬γ³γγΌδΈγ«γοΏ½?ι’ζ°γεΌγ³εΊγγΎγγ欑εδ»₯ιοΏ½?γ¬γ³γγΌγ§γ―γη΄εοΏ½?γ¬γ³γγΌγ¨dependenciesγε€εγγ¦γγͺγγγ°γεγε€γεεΊ¦θΏγγΎγγdependenciesγε€εγγ¦γγγ°γcalculateValueγεΌγ³εΊγγ¦γοΏ½?η΅ζγθΏγγεζγ«γεΎγγεε©η¨γγγγγ«γοΏ½?η΅ζγδΏεγγΎγγ -
dependencies:calculateValueοΏ½?γ³γΌγε γ§εη §γγγ¦γγγγΉγ¦οΏ½?γͺγ’γ―γγ£γε€οΏ½?ι εγγͺγ’γ―γγ£γε€γ«γ―γpropsγstateγγγγ³γ³γ³γγΌγγ³γζ¬δ½γ§η΄ζ₯οΏ½?οΏ½θ¨γγγ¦γγγγΉγ¦οΏ½?ε€ζ°γ¨ι’ζ°γε«γΎγγΎγγγͺγ³γΏγ React εγγ«θ¨οΏ½?οΏ½γγγ¦γγε ΄εγ―γγγΉγ¦οΏ½?γͺγ’γ―γγ£γε€γζ£γγδΎεε€γ¨γγ¦ζοΏ½?οΏ½γγγ¦γγγγη’ΊθͺγγΎγγδΎει εγ―γ[dep1, dep2, dep3]οΏ½?γγγ«γ€γ³γ©γ€γ³γ§θ¨θΏ°γγγι εοΏ½?ι·γγ―δΈοΏ½?οΏ½γ§γγεΏ θ¦γγγγΎγγεδΎεε€γ―γObject.isγη¨γγ¦γεεοΏ½?ε€γ¨ζ―θΌγγγΎγγ
θΏγε€
εεοΏ½?γ¬γ³γγΌγ§γ―γεΌζ°γͺγγ§ calculateValue γεΌγ³εΊγγη΅ζγγuseMemo οΏ½?θΏγε€γ¨γͺγγΎγγ
欑εδ»₯ιοΏ½?γ¬γ³γγΌγ§γ―γδΎει
εγε€εγγ¦γγͺγε ΄εγ―γδ»₯εοΏ½?γ¬γ³γγΌγ§δΏεγγγε€γθΏγγΎγγε€εγγ¦γγε ΄εγ―γcalculateValue γεεΊ¦εΌγ³εΊγγγοΏ½?η΅ζγγοΏ½?γΎγΎθΏγγΎγγ
注ζηΉ
useMemoγ―γγγ―γͺοΏ½?γ§γγ«γΉγΏγ γγγ―γγ³γ³γγΌγγ³γοΏ½?γγγγ¬γγ«γ§γγεΌγ³εΊγγγ¨γγ§γγΎγγγγ«γΌγγζ‘δ»Άεε²οΏ½?δΈγ§εΌγ³εΊγγγ¨γ―γ§γγΎγγγγγγ«γΌγγζ‘δ»Άεε²οΏ½?δΈγ§εΌγ³εΊγγγε ΄εγ―γζ°γγγ³γ³γγΌγγ³γγ«εγεΊγγ¦γγοΏ½?δΈγ« state γη§»εγγγ¦γγ γγγ- Strict Mode γ§γ―γη΄η²γ§γͺγι’ζ°γθ¦γ€γγγγγγγγγ«γθ¨οΏ½?οΏ½ι’ζ° (
calculateValue) γ 2 εΊ¦εΌγ³εΊγγγΎγγγγγ―γιηΊζοΏ½?γΏοΏ½?ζεγ§γζ¬ηͺγ§γ―ε½±ιΏγ―δΈγγΎγγγγγγθ¨οΏ½?οΏ½ι’ζ°γη΄η²γ§γγγ°οΌη΄η²γ§γγγΉγγ§γοΌγ2 εεΌγ³εΊγγγ¦γγ³γΌγγ«ε½±ιΏγ―γγγΎγγγ2 εοΏ½?εΌγ³εΊγοΏ½?γγ‘γδΈζΉοΏ½?εΌγ³εΊγη΅ζγ―η‘θ¦γγγΎγγ - ηΉε₯γͺηη±γγͺγιγγγγ£γγ·γ₯γγγε€γη ΄ζ£γγγγγ¨γ―γγγΎγγγγγ£γγ·γ₯γη ΄ζ£γγγγ±γΌγΉοΏ½?δΎγ¨γγ¦γ―γιηΊζγ«γ³γ³γγΌγγ³γοΏ½?γγ‘γ€γ«γη·¨ιγγε ΄εγγγγΎγγγΎγγιηΊζγγγ³ζ¬ηͺζγ«γεεγγ¦γ³γδΈγ«γ³γ³γγΌγγ³γγγ΅γΉγγ³γγγγ¨γγγ£γγ·γ₯γ―η ΄ζ£γγγΎγγε°ζ₯ηγ«γ―γγγ£γγ·γ₯γη ΄ζ£γγγγγ¨γεζγ¨γγζ©θ½γ React γ«θΏ½ε γγγε―θ½ζ§γγγγΎγγδΎγγ°γε°ζ₯ηγ«οΏ½?ζ³γͺγΉγγη΅γΏθΎΌγΏγ§γ΅γγΌγγγγε ΄εγοΏ½?ζ³γγΌγγ«οΏ½?γγ₯γΌγγΌγγγγΉγ―γγΌγ«γ’γ¦γγγι
οΏ½?γ―γγγ£γγ·γ₯γη ΄ζ£γγγγγ«γͺγγγγγγΎγγγγοΏ½?γγγͺζεγ―γγγγ©γΌγγ³γΉζι©εοΏ½?γΏγοΏ½?ηγ¨γγ¦
useMemoγδ½Ώγ£γ¦γγε ΄εγ«γ―ει‘γγγΎγγγγγγγδ»οΏ½?οΏ½?ηγ§ε©η¨γγ¦γγε ΄εγ―γstate ε€ζ° γ ref γε©η¨γγζΉγθ―γγγγγγΎγγγ
δ½Ώη¨ζ³
ι«γ³γΉγγͺεθ¨οΏ½?οΏ½γιΏγγ
θ€ζ°γ¬γ³γγΌγθ·¨γγ§θ¨οΏ½?οΏ½γγγ£γγ·γ₯γγγ«γ―γγ³γ³γγΌγγ³γοΏ½?γγγγ¬γγ«γ§ useMemo γεΌγ³εΊγγθ¨οΏ½?οΏ½γγ©γγγγΎγγ
import { useMemo } from 'react';
function TodoList({ todos, tab, theme }) {
const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
// ...
}useMemo γ«γ―γ2 γ€οΏ½?εΌζ°γζΈ‘γεΏ
θ¦γγγγΎγγ
() =>οΏ½?γγγ«γεΌζ°γεγγγζ±γγγθ¨οΏ½?οΏ½η΅ζγθΏγθ¨οΏ½?οΏ½ι’ζ°γ- γ³γ³γγΌγγ³γε γ«γγε€οΏ½?γγ‘γθ¨οΏ½?οΏ½ι’ζ°ε γ§δ½Ώη¨γγγ¦γγγγΉγ¦οΏ½?ε€γε«γγδΎει εγ
εεγ¬γ³γγΌγ§γ―γuseMemo γγθΏγγγε€γ―γθ¨οΏ½?οΏ½ι’ζ°γεΌγ³εΊγγη΅ζγ«γͺγγΎγγ
欑εδ»₯ιοΏ½?γ¬γ³γγΌγ§γ―γδ»εοΏ½?γ¬γ³γγΌζγ«ζΈ‘γγδΎει
εγ¨γεεοΏ½?γ¬γ³γγΌζγ«ζΈ‘γγδΎει
εγζ―θΌγγγΎγγοΌObject.is γ§ζ―θΌγγΎγγοΌδΎεε€οΏ½?γγγγε€εγγ¦γγͺγε ΄εγuseMemo γ―δ»₯εγ«θ¨οΏ½?οΏ½γγε€γθΏγγΎγγε€εγγ¦γγε ΄εγ―γεεΊ¦θ¨οΏ½?οΏ½γοΏ½?οΏ½θ‘γγγζ°γγε€γθΏγγγΎγγ
γ€γΎγ useMemo γ―γδΎει
εγε€εγγͺγιγγθ€ζ°οΏ½?γ¬γ³γγΌγθ·¨γγ§θ¨οΏ½?οΏ½η΅ζγγγ£γγ·γ₯γγΎγγ
γγγε½Ήγ«η«γ€ε ΄ι’γθ¦γ¦γΏγΎγγγγ
React γ§γ―ιεΈΈγεγ¬γ³γγΌγηΊηγγγγ³γ«γγ³γ³γγΌγγ³γι’ζ°ε
¨δ½γεοΏ½?οΏ½θ‘γγγΎγγδΎγγ°γδ»₯δΈοΏ½? TodoList γ§γstate γζ΄ζ°γγγγγθ¦ͺγγζ°γγ props γεγεγ£γγγγε ΄εγfilterTodos ι’ζ°γεοΏ½?οΏ½θ‘γγγΎγγ
function TodoList({ todos, tab, theme }) {
const visibleTodos = filterTodos(todos, tab);
// ...
}γ»γ¨γγ©οΏ½?θ¨οΏ½?οΏ½γ―ιεΈΈγ«ι«ιγ«ε¦ηγγγγγγδ½γει‘γ«γͺγγγ¨γ―ιεΈΈγγγΎγγγγγγγε·¨ε€§γͺι
εγγγ£γ«γΏγͺγ³γ°γ»ε€ζγγ¦γγε ΄εγγι«γ³γΉγγͺθ¨οΏ½?οΏ½γθ‘γ£γ¦γγε ΄εγ«γ―γγγΌγΏγε€γγ£γ¦γγͺγγγ°γγγοΏ½?θ¨οΏ½?οΏ½γγΉγγγγγγγͺγγ§γγγγtodos γ¨ tab οΏ½?ε€γεεοΏ½?γ¬γ³γγΌζγ¨εγε ΄εγε
γ»γ©οΏ½?γγγ«θ¨οΏ½?οΏ½γ useMemo γ§γ©γγγγγγ¨γ§γδ»₯εγ«θ¨οΏ½?οΏ½γγ visibleTodos γεε©η¨γγγγ¨γγ§γγοΏ½?γ§γγ
γοΏ½?γγγͺγγ£γγ·γ₯οΏ½?γγ¨γγγ‘γ’εγ¨εΌγ³γΎγγ
γγγ«ζ·±γη₯γ
δΈθ¬ηγ«γδ½εγοΏ½?γͺγγΈγ§γ―γγδ½ζγγγγ«γΌγγγγγγ¦γγͺγιγγγγγγι«δΎ‘γ§γ―γγγΎγγγγγη’ΊδΏ‘γζγ‘γγε ΄εγ―γγ³γ³γ½γΌγ«γγ°γθΏ½ε γγ¦γγ³γΌγοΏ½?οΏ½?οΏ½θ‘γ«γγγ£γζιγθ¨ζΈ¬γγγγ¨γγ§γγΎγγ
console.time('filter array');
const visibleTodos = filterTodos(todos, tab);
console.timeEnd('filter array');ζΈ¬οΏ½?οΏ½γγγγ¦γΌγΆζδ½οΌδΎγγ°γε
₯εγγ£γΌγ«γγΈοΏ½?γΏγ€γοΌγοΏ½?οΏ½θ‘γγΎγγγοΏ½?εΎγγ³γ³γ½γΌγ«γ« filter array: 0.15ms οΏ½?γγγͺγγ°γ葨瀺γγγΎγγε
¨δ½οΏ½?γγ°ζιγγγͺγοΏ½?ιοΌδΎγγ° 1ms δ»₯δΈοΌγ«γͺγε ΄εγγοΏ½?θ¨οΏ½?οΏ½γγ‘γ’εγγζε³γγγγγγγγΎγγγοΏ½?οΏ½ι¨γ¨γγ¦ useMemo γ§θ¨οΏ½?οΏ½γγ©γγγγ¦γΏγ¦γγοΏ½?ζδ½γ«ε―Ύγγεθ¨ζιγζΈε°γγγγ©γγγγγ°γ§η’Ίθͺγ§γγΎγγ
console.time('filter array');
const visibleTodos = useMemo(() => {
return filterTodos(todos, tab); // Skipped if todos and tab haven't changed
}, [todos, tab]);
console.timeEnd('filter array');useMemo γ―εεγ¬γ³γγΌγι«ιεγγΎγγγζ΄ζ°ζγ«δΈθ¦γͺδ½ζ₯γγΉγγγγγγ¨γγ«οΏ½?γΏε½Ήη«γ‘γΎγγ
γΎγγγ»γ¨γγ©οΏ½?ε ΄εγ«γγγͺγγδ½Ώγ£γ¦γγγγ·γ³γ―γγ¦γΌγΆοΏ½?γγ·γ³γγι«ιγ«εδ½γγγ§γγγγγ¨γεΏγγ¦γ―γγγΎγγγγοΏ½?γγγζε³ηγ«ε¦ηιεΊ¦γδ½δΈγγγ¦γγγ©γΌγγ³γΉγγγΉγγγοΏ½?γθ―γγ§γγγγδΎγγ°γChrome γ§γ― CPU γΉγγγγͺγ³γ°γͺγγ·γ§γ³γζδΎγγγ¦γγΎγγ
γΎγγιηΊη°ε’γ§οΏ½?γγγ©γΌγγ³γΉζΈ¬οΏ½?οΏ½γ§γ―οΏ½?οΏ½ε ¨γ«ζ£η’Ίγͺη΅ζγ―εΎγγγͺγγγ¨γ«ζ³¨ζγγ¦γγ γγγοΌδΎγγ°γStrict Mode γγͺγ³οΏ½?ε ΄εγεγ³γ³γγΌγγ³γγ 1 εΊ¦γ§γ―γͺγ 2 εΊ¦γ¬γ³γγΌγγγγγ¨γγγγΎγγοΌζγζ£η’Ίγ«γγγ©γΌγγ³γΉγθ¨ζΈ¬γγγγγ«γ―γγ’γγͺγζ¬ηͺη°ε’η¨γ«γγ«γγγγ¦γΌγΆγζγ£γ¦γγγγγͺγγγ€γΉγ§γγΉγγγ¦γγ γγγ
γγγ«ζ·±γη₯γ
γγͺγοΏ½?γ’γγͺγγοΏ½?γ΅γ€γοΏ½?γγγ«γγ»γ¨γγ©οΏ½?γ€γ³γΏγ©γ―γ·γ§γ³γε€§γΎγγͺγοΏ½?οΌγγΌγΈε ¨δ½γγ»γ―γ·γ§γ³ε ¨δ½οΏ½?οΏ½?γζγγͺγ©οΌγ§γγε ΄εγγ‘γ’εγ―ιεΈΈδΈθ¦γ§γγδΈζΉγγγͺγοΏ½?γ’γγͺγζη»γ¨γγ£γΏοΏ½?γγγͺγοΏ½?γ§γγ»γ¨γγ©οΏ½?γ€γ³γΏγ©γ―γ·γ§γ³γη΄°γγͺγοΏ½?οΌε³ε½’γη§»εγγγγͺγ©οΌγ§γγε ΄εγγ‘γ’εγ―ιεΈΈγ«ε½Ήγ«η«γ€γ§γγγγ
useMemo γε©η¨γγζι©εγεγηΊοΏ½?γγοΏ½?γ―γδ»₯δΈοΏ½?γγγͺγγ»γοΏ½?δΈι¨οΏ½?γ±γΌγΉγ«ιγγγΎγγ
useMemoγ§θ‘γθ¨οΏ½?οΏ½γθγγι γγγγ€γγοΏ½?δΎεε€γγ»γ¨γγ©ε€εγγͺγε ΄εγ- θ¨οΏ½?οΏ½γγε€γγ
memoγ§γ©γγγγγγ³γ³γγΌγγ³γοΏ½? props γ«ζΈ‘γε ΄εγγοΏ½?ε ΄εγ―γε€γε€εγγ¦γγͺγε ΄εγ«γ―εγ¬γ³γγΌγγΉγγγγγγγ§γγγγγ‘γ’εγγγγ¨γ§γδΎεε€γη°γͺγε ΄εγ«οΏ½?γΏγ³γ³γγΌγγ³γγεγ¬γ³γγΌγγγγγ¨γγ§γγΎγγ - γοΏ½?ε€γγεΎγ§δ½γγοΏ½?γγγ―οΏ½?δΎεε€γ¨γγ¦δ½Ώη¨γγγγ±γΌγΉγδΎγγ°γε₯οΏ½?
useMemoοΏ½?θ¨οΏ½?οΏ½η΅ζγγοΏ½?ε€γ«δΎεγγ¦γγε ΄εγγuseEffectγγοΏ½?ε€γ«δΎεγγ¦γγε ΄εγͺγ©γ§γγ
γγγοΏ½?γ±γΌγΉδ»₯ε€γ§γ―γθ¨οΏ½?οΏ½γ useMemo γ§γ©γγγγγγ¨γ«γ‘γͺγγγ―γγγΎγγγγγγθ‘γ£γ¦γιε€§γͺοΏ½?οΏ½γ―γͺγγγγεε₯οΏ½?γ±γΌγΉγθγγγ«γε―θ½γͺιγγγΉγ¦γγ‘γ’εγγγγγ«γγ¦γγγγΌγ γγγγΎγγγοΏ½?γ’γγγΌγοΏ½?γγ‘γͺγγγ―γγ³γΌγγθͺγΏγ«γγγͺγγ¨γγηΉγ§γγγΎγγγγΉγ¦οΏ½?γ‘γ’εγζεΉγ§γγγγγ§γ―γγγΎγγγδΎγγ°γζ―εε€εγγε€γ 1 γ€εε¨γγγ γγ§γγ³γ³γγΌγγ³γε
¨δ½οΏ½?γ‘γ’εγη‘ζε³γ«γͺγ£γ¦γγΎγγγ¨γγγγΎγγ
οΏ½?οΏ½ιγ«γ―γδ»₯δΈοΏ½?γγγ€γοΏ½?εεγ«εΎγγγ¨γ§γε€γοΏ½?γ‘γ’εγδΈθ¦γ«γγγγ¨γγ§γγΎγγ
- γ³γ³γγΌγγ³γγδ»οΏ½?γ³γ³γγΌγγ³γγθ¦θ¦ηγ«γ©γγγγγ¨γγ―γγγγεγ¨γγ¦ JSX γεγε ₯γγγγγ«γγΎγγγγγ«γγγγ©γγγ³γ³γγΌγγ³γγθͺθΊ«οΏ½? state γζ΄ζ°γγ¦γγReact γ―γοΏ½?εγεγ¬γ³γγΌγγεΏ θ¦γγͺγγγ¨γθͺθγγΎγγ
- γγΌγ«γ« state γεͺε γγεΏ θ¦δ»₯δΈγ« state οΏ½?γͺγγγ’γγγθ‘γγͺγγγγ«γγΎγγγγ©γΌγ γγγ’γ€γγ γγγγΌγγγ¦γγγγ©γγγγ¨γγ£γι »ηΉγ«ε€εγγ state γ―γγγͺγΌοΏ½?γγγγγ°γγΌγγ«οΏ½?ηΆζ γ©γ€γγ©γͺγ«δΏζγγͺγγ§γγ γγγ
- γ¬γ³γγΌγγΈγγ―γη΄η²γ«δΏγ‘γΎγγγ³γ³γγΌγγ³γοΏ½?εγ¬γ³γγΌγει‘γεΌγθ΅·γγγγγδ½γγοΏ½?οΏ½?γ«θ¦γγθ¦θ¦ηγͺη΅ζγηγγγγγε ΄εγγγγ―γγͺγοΏ½?γ³γ³γγΌγγ³γοΏ½?γγ°γ§γοΌ γ‘γ’εγθΏ½ε γγοΏ½?γ§γ―γͺγγγγ°γοΏ½?ζ£γγΎγγ
- state γζ΄ζ°γγδΈθ¦γͺγ¨γγ§γ―γγιΏγγ¦γγ γγγReact γ’γγͺγ±γΌγ·γ§γ³οΏ½?γγγ©γΌγγ³γΉει‘οΏ½?ε€§ι¨εγ―γγ¨γγ§γ―γε γ§οΏ½?ι£ιηγͺ state ζ΄ζ°γ«γγ£γ¦γ³γ³γγΌγγ³γοΏ½?γ¬γ³γγΌγδ½εΊ¦γεΌγθ΅·γγγγγγγ«ηγγΎγγ
- γ¨γγ§γ―γγγδΈθ¦γͺδΎεε€γγ§γγγ γει€γγΎγγδΎγγ°γγ‘γ’εγγ代γγγ«γγͺγγΈγ§γ―γγι’ζ°γγ¨γγ§γ―γοΏ½?δΈγε€γ«η§»εγγγγ γγ§γη°‘εγ«θ§£ζ±Ίγ§γγε ΄εγγγγΎγγ
γγγ§γηΉοΏ½?οΏ½οΏ½?γ€γ³γΏγ©γ―γ·γ§γ³γι γγ¨ζγγε ΄εγ―γReact Developer Tools οΏ½?γγγγ‘γ€γ©γδ½Ώη¨γγ¦γγ©οΏ½?γ³γ³γγΌγγ³γγ§οΏ½?γ‘γ’εγζγζεΉγγη’Ίθͺγγγγγ§γ‘γ’εγθ‘γγΎγγγγγγγοΏ½?εεγοΏ½?οΏ½γγγ¨γ§γγ³γ³γγΌγγ³γοΏ½?γγγγ°γηθ§£γοΏ½?οΏ½ζγ«γͺγγγγεΈΈγ«εεγ«εΎγγγ¨γγγγγγγΎγγι·ζηγ«γ―γγοΏ½?ει‘γδΈζγ«θ§£ζ±Ίγ§γγθͺεηγͺγ‘γ’εγ«γ€γγ¦η η©Άγθ‘γ£γ¦γγΎγγ
δΎ 1/2: useMemo γε©η¨γγ¦εθ¨οΏ½?οΏ½γγΉγγγγγ
γοΏ½?δΎγ§γ― filterTodos οΏ½?οΏ½?οΏ½θ£
γ«γ―δΊΊηΊηγͺι
ε»Άγε
₯γ£γ¦γγΎγγγοΏ½?γγγγ¬γ³γγΌδΈγ«εΌγ³εΊγ JavaScript οΏ½?ι’ζ°οΏ½?ε¦ηγθγγι
γε ΄εγ«γγ©γγͺγγγη’Ίθͺγ§γγΎγγγΏγγεγζΏγγγγγγΌγγεγζΏγγ¦γΏγ¦γγ γγγ
γΏγοΏ½?εγζΏγγι
γζγγγγοΏ½?γ―γεγζΏγγ«γγ£γ¦γι
ε»Άγε
₯γ£γ¦γγ filterTodos ι’ζ°γεοΏ½?οΏ½θ‘γγγ¦γγΎγ£γ¦γγγγγ§γγγοΏ½?ζεγ―θγγ¦γΏγγ°ε½γγεγ§γtab γε€εγγοΏ½?γͺγγθ¨οΏ½?οΏ½ε
¨δ½γεοΏ½?οΏ½θ‘γγεΏ
θ¦γγγγ―γγ§γγοΌγͺγ 2 εοΏ½?οΏ½θ‘γγγοΏ½?γζ°γ«γͺγε ΄εγ―γγγ‘γγεη
§γγ¦γγ γγοΌ
欑γ«γγγΌγγεγζΏγγ¦γΏγΎγγγγuseMemo γγγγγγγ§γδΊΊηΊηγͺι
ε»Άγε
₯γ£γ¦γγγ«γι’γγγγι«ιγ«εδ½γγ¦γγΎγοΌ todos γ¨ tabοΌuseMemo οΏ½?δΎει
εγ¨γγ¦ζΈ‘γγ¦γγοΌγγεεοΏ½?γ¬γ³γγΌζγγε€εγγ¦γγͺγγγγι
ε»Άγε
₯γ£γ¦γγ filterTodos οΏ½?εΌγ³εΊγγγΉγγγγγγ¦γγΎγγ
import { useMemo } from 'react'; import { filterTodos } from './utils.js' export default function TodoList({ todos, theme, tab }) { const visibleTodos = useMemo( () => filterTodos(todos, tab), [todos, tab] ); return ( <div className={theme}> <p><b>Note: <code>filterTodos</code> is artificially slowed down!</b></p> <ul> {visibleTodos.map(todo => ( <li key={todo.id}> {todo.completed ? <s>{todo.text}</s> : todo.text } </li> ))} </ul> </div> ); }
γ³γ³γγΌγγ³γοΏ½?εγ¬γ³γγΌγγΉγγγγγ
useMemo γ―γεγ³γ³γγΌγγ³γοΏ½?εγ¬γ³γγΌοΏ½?γγγ©γΌγγ³γΉγζι©εγγιγ«γε½Ήγ«η«γ€γγ¨γγγγΎγγγγγθͺ¬ζγγγγγ«γTodoList γ³γ³γγΌγγ³γγγεγ³γ³γγΌγγ³γοΏ½? List οΏ½? props γ¨γγ¦γvisibleTodos γζΈ‘γγγ¨γθγγΎγγ
export default function TodoList({ todos, tab, theme }) {
// ...
return (
<div className={theme}>
<List items={visibleTodos} />
</div>
);
}props γ§γγ theme γε€εγγγγ¨δΈη¬γ’γγͺγγγͺγΌγΊγγΎγγγ<List /> γ JSX γγει€γγγ¨γι«ιγ«εδ½γγγγγ«γͺγ£γγ―γγ§γγγγͺγγ‘γγοΏ½? List γ³γ³γγΌγγ³γγ«γ―ζι©εγγδΎ‘ε€γγγγ¨γγγγ¨γ§γγ
ιεΈΈγγγγ³γ³γγΌγγ³γγεγ¬γ³γγΌγγγγ¨γγ―γγοΏ½?εγ³γ³γγΌγγ³γγεεΈ°ηγ«γγΉγ¦εγ¬γ³γγΌγγγΎγγγγγγTodoList γη°γͺγ theme οΏ½?ε€γ§εγ¬γ³γγΌγγγγ¨γγList γ³γ³γγΌγγ³γγδΈη·γ«εγ¬γ³γγΌγγγηη±γ§γγγοΏ½?εδ½γ―γεγ¬γ³γγΌγ«γγγ»γ©ε€γοΏ½?θ¨οΏ½?οΏ½γ³γΉγγεΏ
θ¦γ¨γγͺγγ³γ³γγΌγγ³γγ«γ―ι©γγ¦γγΎγγγγγγγγεγ¬γ³γγΌγι
γγ¨εγγ£γε ΄εγ―γList γ³γ³γγΌγγ³γγ memo γ§ε²γγγ¨γ§γδΈγγγγ props γεεοΏ½?γ¬γ³γγΌγ¨εγγ§γγε ΄εγ« List οΏ½?εγ¬γ³γγΌγγΉγγγγγγγ¨γγ§γγΎγγ
import { memo } from 'react';
const List = memo(function List({ items }) {
// ...
});γοΏ½?ε€ζ΄γ«γγ£γ¦γprops οΏ½?ε
¨ι
οΏ½?γεεοΏ½?γ¬γ³γγΌγ¨ηγγε ΄εγ«γ―γList οΏ½?εγ¬γ³γγΌγ―γΉγγγγγγγγγ«γͺγγΎγγγγγγθ¨οΏ½?οΏ½οΏ½?γγ£γγ·γ₯γιθ¦γ«γͺγηη±γ§γοΌ useMemo γδ½Ώγγγ« visibleTodos οΏ½?θ¨οΏ½?οΏ½γθ‘γγγ¨γζ³εγγ¦γΏγ¦γγ γγγ
export default function TodoList({ todos, tab, theme }) {
// Every time the theme changes, this will be a different array...
const visibleTodos = filterTodos(todos, tab);
return (
<div className={theme}>
{/* ... so List's props will never be the same, and it will re-render every time */}
<List items={visibleTodos} />
</div>
);
}δΈθ¨οΏ½?δΎγ§γ―γfilterTodos ι’ζ°γζ―εη°γͺγι
εγηζγγΎγγοΌγγγ―γ{} γ¨γγγͺγγΈγ§γ―γγͺγγ©γ«γγζ―εζ°γγγͺγγΈγ§γ―γγηζγγγγ¨γ¨δΌΌγ¦γγΎγγοΌιεΈΈγγγει‘γ«γͺγγγ¨γ―γγγΎγγγγδ»εοΏ½?ε ΄εγ―γList οΏ½? props γζ―εε₯οΏ½?ε€γ«γͺγ£γ¦γγΎγγΎγγγοΏ½?γγγmemo γ«γγζι©εγζε³γγͺγγͺγγͺγ£γ¦γγΎγοΏ½?γ§γγγγγ§γuseMemo γε½Ήγ«η«γ‘γΎγγ
export default function TodoList({ todos, tab, theme }) {
// Tell React to cache your calculation between re-renders...
const visibleTodos = useMemo(
() => filterTodos(todos, tab),
[todos, tab] // ...so as long as these dependencies don't change...
);
return (
<div className={theme}>
{/* ...List will receive the same props and can skip re-rendering */}
<List items={visibleTodos} />
</div>
);
}visibleTodos οΏ½?θ¨οΏ½?οΏ½γ useMemo γ§γ©γγγγγγ¨γ§γθ€ζ°οΏ½?εγ¬γ³γγΌοΏ½?ιγ§γοΏ½?η΅ζγεγγ«γͺγγγ¨γδΏθ¨Όγ§γγΎγοΌδΎει
εγε€γγγͺγιγοΌγιεΈΈγηΉε₯γͺηη±γγͺγγγ°γθ¨οΏ½?οΏ½γ useMemo γ§γ©γγγγεΏ
θ¦γ―γγγΎγγγγοΏ½?δΎγ§γ―γmemo γ§ε²γγγγ³γ³γγΌγγ³γγ«ε€γζΈ‘γγ¦γγγ¬γ³γγΌοΏ½?γΉγγγγγ§γγγ¨γγγγ¨γγγοΏ½?ηΉε₯γͺηη±γ«γγγγΎγγδ»γ«γ useMemo γθΏ½ε γγεζ©γ―γγγ€γγγγγοΏ½?γγΌγΈγ§θ©³γγθ§£θͺ¬γγ¦γγγΎγγ
γγγ«ζ·±γη₯γ
List γ memo γ§γ©γγγγ代γγγ«γ<List /> JSX γγΌγθͺδ½γ useMemo γ§γ©γγγγ¦γζ§γγΎγγγ
export default function TodoList({ todos, tab, theme }) {
const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
const children = useMemo(() => <List items={visibleTodos} />, [visibleTodos]);
return (
<div className={theme}>
{children}
</div>
);
}ζεγ―εγγ«γͺγγΎγγvisibleTodos γε€εγγ¦γγͺγε ΄εγ―γList γ―εγ¬γ³γγΌγγγΎγγγ
<List items={visibleTodos} /> οΏ½?γγγͺ JSX γγΌγγ―γ{ type: List, props: { items: visibleTodos } } οΏ½?γγγͺγͺγγΈγ§γ―γγ¨εγγ§γγγοΏ½?γͺγγΈγ§γ―γγδ½ζγγγ³γΉγγ―ιεΈΈγ«ε°γγγ§γγγReact γ―γοΏ½?ε
οΏ½?οΏ½γεεοΏ½?ε
οΏ½?οΏ½γ¨εγγγ©γγγ―εγγγΎγγγγοΏ½?γγγReact γ―γγγγ©γ«γγ§ List γ³γ³γγΌγγ³γγεγ¬γ³γγΌγγοΏ½?γ§γγ
γγγγReact γεεοΏ½?γ¬γ³γγΌζγ¨ε
¨γεγ JSX γθ¦γ€γγε ΄εγγ³γ³γγΌγγ³γοΏ½?εγ¬γ³γγΌγ―θ‘γγΎγγγγγγ―γJSX γγΌγγγ€γγ₯γΌγΏγγ« (immutable) γ§γγγγγ§γγJSX γγΌγγͺγγΈγ§γ―γγ―ζιγη΅ιγγ¦γε€εγγγγ¨γ―γͺγγγγεγ¬γ³γγΌγγΉγγγγγ¦γγΎγ£γ¦ει‘γγγΎγγγγγγγγγγζ©θ½γγγ«γ―γγγΌγγηγ«ε
¨γεδΈοΏ½?γͺγγΈγ§γ―γγ§γγεΏ
θ¦γγγγγ³γΌγδΈγ§εγγγγ«θ¦γγγ γγ§γ―δΈεεγ§γγγοΏ½?δΎγ§γ―γuseMemo οΏ½?γγγγ§γγγΌγγε
¨γεγγͺγγΈγ§γ―γγ¨γͺγ£γ¦γγοΏ½?γ§γγ
useMemo γδ½Ώγ£γ¦γJSX γγΌγγζεγ§γ©γγγγοΏ½?γ―δΈδΎΏγ§γγδΎγγ°γζ‘δ»Άδ»γγ§γ©γγγγγγ¨γ―γ§γγΎγγγγοΏ½?γγγιεΈΈγ― useMemo γ§ JSX γγΌγγγ©γγγγ代γγγ«γmemo γ§γ³γ³γγΌγγ³γγγ§γ©γγγγΎγγ
δΎ 1/2: useMemo γ¨ memo γε©η¨γγ¦εγ¬γ³γγΌγγΉγγγγγ
γοΏ½?δΎγ§γ―γList γ³γ³γγΌγγ³γγ«γ―δΊΊηΊηγͺι
ε»Άγε
₯γ£γ¦γγΎγγγοΏ½?γγγγ¬γ³γγΌδΈγ«εΌγ³εΊγγ¦γγ React γ³γ³γγΌγγ³γγθγγι
γε ΄εοΏ½?ζεγη’Ίθͺγ§γγΎγγγΏγγε€ζ΄γγγγγγΌγγεγζΏγγγγγ¦γΏγ¦γγ γγγ
γΏγοΏ½?εγζΏγγι
γζγγοΏ½?γ―γι
ε»Άγε
₯γ£γ¦γγ List γεγ¬γ³γγΌγγγ¦γγΎγ£γ¦γγγγγ§γγγγγ―θγγ¦γΏγγ°ε½ηΆγ§γtab γε€εγγοΏ½?γ§γγ¦γΌγΆοΏ½?ζ°γγιΈζγη»ι’γ«εζ γγεΏ
θ¦γγγγΎγγ
欑γ«γγγΌγγεγζΏγγ¦γΏγΎγγγγuseMemo γ¨ memo γγγγγγγ§γδΊΊηΊηγͺι
ε»Άγγγγ«γι’γγγγι«ιγ«εδ½γγ¦γγΎγοΌ visibleItems ι
εγεεοΏ½?γ¬γ³γγΌζγγε€εγγ¦γγͺγγγγList γ―εγ¬γ³γγΌγγΉγγγγγ¦γγΎγγvisibleItems ι
εγε€εγγ¦γγͺγοΏ½?γ―γtodos γ¨ tabοΌuseMemo οΏ½?δΎει
εγ¨γγ¦ζΈ‘γγ¦γγοΌγγεεοΏ½?γ¬γ³γγΌζγγε€εγγ¦γγͺγγγγ§γγ
import { useMemo } from 'react'; import List from './List.js'; import { filterTodos } from './utils.js' export default function TodoList({ todos, theme, tab }) { const visibleTodos = useMemo( () => filterTodos(todos, tab), [todos, tab] ); return ( <div className={theme}> <p><b>Note: <code>List</code> is artificially slowed down!</b></p> <List items={visibleTodos} /> </div> ); }
δ»οΏ½?γγγ―γ«ζΈ‘γδΎεε€γγ‘γ’εγγ
γγθ¨οΏ½?οΏ½γγγ³γ³γγΌγγ³γοΏ½?ζ¬δ½γ§η΄ζ₯δ½ζγγγγͺγγΈγ§γ―γγ«δΎεγγ¦γγγ¨γγΎγγγγ
function Dropdown({ allItems, text }) {
const searchOptions = { matchMode: 'whole-word', text };
const visibleItems = useMemo(() => {
return searchItems(allItems, searchOptions);
}, [allItems, searchOptions]); // π© Caution: Dependency on an object created in the component body
// ...γοΏ½?γγγͺγͺγγΈγ§γ―γγδΎεε€γ¨γγ¦δ½Ώγγ¨γ‘γ’εοΏ½?ζε³γγͺγγͺγ£γ¦γγΎγγΎγγγ³γ³γγΌγγ³γγεγ¬γ³γγΌγγγγ¨γγγ³γ³γγΌγγ³γοΏ½?ζ¬δ½γ«ε«γΎγγγ³γΌγγ―γγΉγ¦εοΏ½?οΏ½θ‘γγγΎγγsearchOptions γͺγγΈγ§γ―γγδ½ζγγγ³γΌγγγζ―εεοΏ½?οΏ½θ‘γγγΎγγsearchOptions γ― useMemo οΏ½?δΎεε€γ§γγγζ―εη°γͺγε€γ¨γͺγγγγδΎεε€γε€εγγγ¨ε€ζγγγsearchItems γζ―εεθ¨οΏ½?οΏ½γγγΎγγ
γγγοΏ½?ζ£γγγ«γ―γsearchOptions γͺγγΈγ§γ―γγδΎει
εγ«ζΈ‘γεγ«γsearchOptions γͺγγΈγ§γ―γθͺδ½γγ‘γ’εγγΎγγγγ
function Dropdown({ allItems, text }) {
const searchOptions = useMemo(() => {
return { matchMode: 'whole-word', text };
}, [text]); // β
Only changes when text changes
const visibleItems = useMemo(() => {
return searchItems(allItems, searchOptions);
}, [allItems, searchOptions]); // β
Only changes when allItems or searchOptions changes
// ...δΈθ¨οΏ½?δΎγ§γ―γtext γε€εγγͺγγγ°γsearchOptions γͺγγΈγ§γ―γγε€εγγΎγγγγγγγγγγ«θ―γοΏ½?ζ£ζΉζ³γ―γsearchOptions γͺγγΈγ§γ―γοΏ½?οΏ½?οΏ½θ¨γ useMemo οΏ½?θ¨οΏ½?οΏ½ι’ζ°οΏ½?δΈγ«η§»εγγγγ¨γ§γγ
function Dropdown({ allItems, text }) {
const visibleItems = useMemo(() => {
const searchOptions = { matchMode: 'whole-word', text };
return searchItems(allItems, searchOptions);
}, [allItems, text]); // β
Only changes when allItems or text changes
// ...γγγ§γθ¨οΏ½?οΏ½γη΄ζ₯ text γ«δΎεγγγγγ«γͺγγΎγγγοΌtext γ―ζεεγͺοΏ½?γ§γζε³γγγε€εγγ¦γγΎγγγ¨γ―γγγΎγγγοΌ
ι’ζ°γγ‘γ’εγγ
Form γ³γ³γγΌγγ³γγ memo γ§γ©γγγγγ¦γγγ¨γγΎγγι’ζ°γ props γ¨γγ¦ζΈ‘γγ¦γΏγΎγγγγ
export default function ProductPage({ productId, referrer }) {
function handleSubmit(orderDetails) {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
}
return <Form onSubmit={handleSubmit} />;
}{} γη°γͺγγͺγγΈγ§γ―γγηζγγοΏ½?γ¨εζ§γ«γfunction() {} οΏ½?γγγͺι’ζ°οΏ½?οΏ½θ¨γγ() => {} οΏ½?γγγͺι’ζ°εΌγγΎγγγ¬γ³γγΌγγ¨γ«η°γͺγι’ζ°γηζγγΎγγζ°γγι’ζ°γηζγγγγγ¨θͺδ½γ―ει‘γ§γ―γͺγγιΏγγγΉγγγ¨γ§γγγγΎγγγγγγγForm γ³γ³γγΌγγ³γγγ‘γ’εγγγ¦γγηΆζ³γ§γ―γForm οΏ½? props γ«ζΈ‘γε€γε€γγ£γ¦γγͺγε ΄εγ― Form οΏ½?εγ¬γ³γγΌγγΉγγγγγγγ¨θγγγ§γγγγζ―εη°γͺγε€γ props γ«γγγ¨γγ‘γ’εγ―η‘ζε³γ«γͺγ£γ¦γγΎγγΎγγ
useMemo γ§ι’ζ°γγ‘γ’εγγε ΄εγ―γθ¨οΏ½?οΏ½ι’ζ°γγγγ«ε₯οΏ½?ι’ζ°γθΏγεΏ
θ¦γγγγΎγγ
export default function Page({ productId, referrer }) {
const handleSubmit = useMemo(() => {
return (orderDetails) => {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
};
}, [productId, referrer]);
return <Form onSubmit={handleSubmit} />;
}γͺγγ γδΈζ°ε₯½γ§γγοΌ ι’ζ°οΏ½?γ‘γ’εγ―γγγγγγ¨γͺοΏ½?γ§γγγε°η¨οΏ½?η΅γΏθΎΌγΏγγγ―γζδΎγγγ¦γγΎγγδ½θ¨γͺι’ζ°οΏ½?ε
₯γεγιΏγγγ«γ―γuseMemo οΏ½?代γγγ« useCallback γ§ι’ζ°γγ©γγγγΎγγγγ
export default function Page({ productId, referrer }) {
const handleSubmit = useCallback((orderDetails) => {
post('/product/' + productId + '/buy', {
referrer,
orderDetails
});
}, [productId, referrer]);
return <Form onSubmit={handleSubmit} />;
}δΈθ¨οΏ½? 2 γ€οΏ½?δΎγ―οΏ½?οΏ½ε
¨γ«ηδΎ‘γ§γγuseCallback οΏ½?γ‘γͺγγγ―γδ½θ¨γͺι’ζ°οΏ½?ε
₯γεγδΈθ¦γ«γͺγγγ¨γ γγ§γγγγδ»₯ε€οΏ½?ιγγ―δ½γγγγΎγγγuseCallback γ«γ€γγ¦οΏ½?θ©³η΄°γ―γγγ‘γγεη
§γγ¦γγ γγγ
γγ©γγ«γ·γ₯γΌγγ£γ³γ°
εγ¬γ³γγΌοΏ½?γγ³γ«θ¨οΏ½?οΏ½γ 2 εοΏ½?οΏ½θ‘γγγ
Strict Mode γ§γ―γζ¬ζ₯ 1 εγ γι’ζ°γεΌγ³εΊγγγγ¨γγγ§γ2 εεΌγ³εΊγγγγγ¨γγγγΎγγ
function TodoList({ todos, tab }) {
// This component function will run twice for every render.
const visibleTodos = useMemo(() => {
// This calculation will run twice if any of the dependencies change.
return filterTodos(todos, tab);
}, [todos, tab]);
// ...γγγ―ζ³οΏ½?οΏ½ιγοΏ½?ζεγ§γγγγγγ§γ³γΌγγε£γγγγ¨γγγ£γ¦γ―γγγΎγγγ
γγγ―ιηΊζοΏ½?γΏοΏ½?ζεγ§γιηΊθ γγ³γ³γγΌγγ³γγη΄η²γ«δΏγ€γγγ«ε½Ήη«γ‘γΎγγεΌγ³εΊγη΅ζοΏ½?γγ‘οΏ½? 1 γ€γζ‘η¨γγγγγ 1 γ€γ―η‘θ¦γγγΎγγγγͺγγοΏ½?οΏ½θ£ γγγ³γ³γγΌγγ³γγ¨θ¨οΏ½?οΏ½ι’ζ°γη΄η²γ§γγγ°γγοΏ½?ζεγγγΈγγ―γ«ε½±ιΏγδΈγγγγ¨γ―γγγΎγγγγγγγγγζε³γγη΄η²γ§γ―γͺγι’ζ°γ«γͺγ£γ¦γγε ΄εγ―γγοΏ½?ζεγ«γγ£γ¦ιιγγ«ζ°γ₯γγοΏ½?ζ£γγγγ¨γγ§γγΎγγ
γγ¨γγ°γδ»₯δΈοΏ½?θ¨οΏ½?οΏ½ι’ζ°γ―γprops γ¨γγ¦εγεγ£γι εοΏ½?ζΈγζγοΌγγ₯γΌγγΌγ·γ§γ³οΌγγγ¦γγΎγ£γ¦γγγη΄η²γ§γ―γγγΎγγγ
const visibleTodos = useMemo(() => {
// π© Mistake: mutating a prop
todos.push({ id: 'last', text: 'Go for a walk!' });
const filtered = filterTodos(todos, tab);
return filtered;
}, [todos, tab]);γγγγγοΏ½?ι’ζ°γ― 2 εΊ¦εΌγ³εΊγγγγγγtodo γ 2 εθΏ½ε γγγγγ¨γ«ζ°γ₯γγ―γγ§γγθ¨οΏ½?οΏ½ι’ζ°γ―γζ’εοΏ½?γͺγγΈγ§γ―γγε€ζ΄γγ¦γ―γγγΎγγγγθ¨οΏ½?οΏ½δΈγ«δ½ζγγζ°γγγͺγγΈγ§γ―γγε€ζ΄γγγγ¨γ―ει‘γγγΎγγγγγ¨γγ°γfilterTodos ι’ζ°γεΈΈγ«η°γͺγι
εγθΏγε ΄εγ―γγοΏ½?ι
εγε€ζ΄γγ¦γει‘γγγΎγγγ
const visibleTodos = useMemo(() => {
const filtered = filterTodos(todos, tab);
// β
Correct: mutating an object you created during the calculation
filtered.push({ id: 'last', text: 'Go for a walk!' });
return filtered;
}, [todos, tab]);η΄ι’ζ°γ«γ€γγ¦θ©³γγη₯γγ«γ―γγ³γ³γγΌγγ³γγη΄η²γ«δΏγ€γεη §γγ¦γγ γγγ
γΎγγγγ₯γΌγγΌγ·γ§γ³γͺγγ§γͺγγΈγ§γ―γγζ΄ζ°γγζΉζ³γ«γ€γγ¦γ―γͺγγΈγ§γ―γοΏ½?ζ΄ζ°γγγγ₯γΌγγΌγ·γ§γ³γͺγγ§ι εγζ΄ζ°γγζΉζ³γ«γ€γγ¦γ―ι εοΏ½?ζ΄ζ°γεη §γγ¦γγ γγγ
useMemo οΏ½?θΏγε€γγγͺγγΈγ§γ―γγ§γ―γͺγ undefined γ«γͺγ£γ¦γγΎγ
δ»₯δΈοΏ½?γ³γΌγγ―γγΎγεδ½γγΎγγγ
// π΄ You can't return an object from an arrow function with () => {
const searchOptions = useMemo(() => {
matchMode: 'whole-word',
text: text
}, [text]);JavaScript γ§γ―γ() => { γ¨γγγ³γΌγγ§γ’γγΌι’ζ°οΏ½?ζ¬δ½γιε§γγγγγ{ οΏ½?ζ³’ζ¬εΌ§γ―γͺγγΈγ§γ―γοΏ½?δΈι¨γ«γ―γͺγγΎγγγγγγγ£γ¦γͺγγΈγ§γ―γγ―θΏγγγγγγΉγ«γ€γͺγγγΎγγ({ γ }) οΏ½?γγγ«δΈΈζ¬εΌ§γθΏ½ε γγγγ¨γ§οΏ½?ζ£γ§γγΎγγ
// This works, but is easy for someone to break again
const searchOptions = useMemo(() => ({
matchMode: 'whole-word',
text: text
}), [text]);γγγγγγγ§γγΎγ ζ··δΉ±γγγγγθͺ°γγδΈΈζ¬εΌ§γει€γγ¦γγΎγγ¨η°‘εγ«ε£γγ¦γγΎγγΎγγ
γοΏ½?γγΉγιΏγγγγγ«γζη€Ίηγ« return ζγζΈγγΎγγγγ
// β
This works and is explicit
const searchOptions = useMemo(() => {
return {
matchMode: 'whole-word',
text: text
};
}, [text]);γ³γ³γγΌγγ³γγγ¬γ³γγΌγγγγγ³γ« useMemo ε
οΏ½?ι’ζ°γεοΏ½?οΏ½θ‘γγγ
第 2 εΌζ°γ«δΎει εγζοΏ½?οΏ½γγ¦γγγη’Ίθͺγγ¦γγ γγοΌ
δΎει
εγεΏγγγ¨γuseMemo γ―ζ―εθ¨οΏ½?οΏ½γεοΏ½?οΏ½θ‘γγ¦γγΎγγΎγγ
function TodoList({ todos, tab }) {
// π΄ Recalculates every time: no dependency array
const visibleTodos = useMemo(() => filterTodos(todos, tab));
// ...第 2 εΌζ°γ«δΎει εγζΈ‘γγοΏ½?ζ£ηγ―δ»₯δΈοΏ½?ιγγ§γγ
function TodoList({ todos, tab }) {
// β
Does not recalculate unnecessarily
const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
// ...γγγ§θ§£ζ±Ίγγͺγε ΄εγ―γε°γͺγγ¨γ 1 γ€οΏ½?δΎεε€γεεοΏ½?γ¬γ³γγΌγ¨η°γͺγ£γ¦γγγγ¨γει‘γ§γγζεγ§δΎεε€γγ³γ³γ½γΌγ«γ«εΊεγγ¦γγγγγ°γγγγ¨γγ§γγΎγγ
const visibleTodos = useMemo(() => filterTodos(todos, tab), [todos, tab]);
console.log([todos, tab]);γ³γ³γ½γΌγ«δΈγ§γε₯γ
οΏ½?εγ¬γ³γγΌγ«γγ£γ¦θ‘¨η€Ίγγγ 2 γ€οΏ½?ι
εγιΈγ³γΎγγγγγγγ«γ€γγ¦γι
εγε³γ―γͺγγ―γγβStore as a global variableοΌγ°γγΌγγ«ε€ζ°γ¨γγ¦δΏεοΌβ γιΈζγγγγ¨γ§γι
εγδΏεγγγγ¨γγ§γγΎγγ1 εοΏ½?γ«δΏεγγι
εγ temp1γ2 εοΏ½?γ«δΏεγγι
εγ temp2 γ¨γγ¦δΏεγγγγ¨γγγ¨γγγ©γ¦γΆοΏ½?γ³γ³γ½γΌγ«γδ½Ώη¨γγ¦γδΈ‘ζΉοΏ½?ι
εοΏ½?εδΎεε€γεγγγ©γγγη’Ίθͺγ§γγΎγγ
Object.is(temp1[0], temp2[0]); // Is the first dependency the same between the arrays?
Object.is(temp1[1], temp2[1]); // Is the second dependency the same between the arrays?
Object.is(temp1[2], temp2[2]); // ... and so on for every dependency ...γ‘γ’εγ妨γγ¦γγδΎεε€γθ¦γ€γγγγγοΏ½?δΎεε€γει€γγζΉζ³γζ’γγγγοΏ½?δΎεε€γγ‘γ’εγγΎγγγγ
γ«γΌγε
οΏ½?γͺγΉγοΏ½?ει
οΏ½?γ«γ€γγ¦ useMemo γεΌγ³εΊγγγγγη¦ζ’γγγ¦γγ
Chart γ³γ³γγΌγγ³γγ memo γ§γ©γγγγγ¦γγγ¨γγΎγγReportList γ³γ³γγΌγγ³γγεγ¬γ³γγΌγγγε ΄εγ§γγγͺγΉγε
οΏ½?ε Chart οΏ½?εγ¬γ³γγΌγ―γΉγγγγγγγ§γγγ¨γγγγδ»₯δΈοΏ½?γγγ«γ«γΌγε
γ§ useMemo γεΌγ³εΊγγγ¨γ―γ§γγΎγγγ
function ReportList({ items }) {
return (
<article>
{items.map(item => {
// π΄ You can't call useMemo in a loop like this:
const data = useMemo(() => calculateReport(item), [item]);
return (
<figure key={item.id}>
<Chart data={data} />
</figure>
);
})}
</article>
);
}γοΏ½?ε ΄εγ―γεγ’γ€γγ γγ³γ³γγΌγγ³γγ«εγεΊγγγ’γ€γγ γγ¨γ«γγΌγΏγγ‘γ’εγγΎγγ
function ReportList({ items }) {
return (
<article>
{items.map(item =>
<Report key={item.id} item={item} />
)}
</article>
);
}
function Report({ item }) {
// β
Call useMemo at the top level:
const data = useMemo(() => calculateReport(item), [item]);
return (
<figure>
<Chart data={data} />
</figure>
);
}γγγγ―γuseMemo γει€γγReport θͺδ½γ memo γ§γ©γγγγγγ¨γ§γθ§£ζ±Ίγ§γγΎγγitem γε€εγγͺγε ΄εγ―γReport οΏ½?εγ¬γ³γγΌγ―γΉγγγγγγChart οΏ½?εγ¬γ³γγΌγγΉγγγγγγΎγγ
function ReportList({ items }) {
// ...
}
const Report = memo(function Report({ item }) {
const data = calculateReport(item);
return (
<figure>
<Chart data={data} />
</figure>
);
});