Чтобы изучить useMemo, вы должны сначала знать React.memo
Оба они имеют определенный эффект оптимизации
роль мемо
Когда данные изменяются, код снова будет перезапущен, ноДанные дочернего компонента также будут выполнены, если нет изменений, на этот раз вы можете использоватьmemo
Инкапсулируйте подкомпонент, чтобы данные подкомпонента выполнялись только при изменении данных
кейс
Нажмите кнопку, чтобы изменить значение n, а m останется без изменений.Выполнит ли программа проверки код m?
Когда не используете памятку
Когда изменяется только значение n, хотя значение m не изменяется, также выполняется оператор печати ребенка.
function App(){
const [n,setN] = useState(0);
const [m,setM] = useState(0);
const add=()=>{
setN(i=>i+1);
};
const addChild=()=>{
setM(i=>i+1);
};
return(
<div>
<div>
n:{n}
<button onClick={add}>n+1</button>
<button onClick={addChild}>m+1</button>
</div>
<Child data={m} />
</div>
)
}
function Child(props){
console.log('child执行了')
return(
<div>
child:{props.data}
</div>
)
}
ReactDOM.render(<App />,document.getElementById('root'));
Упаковка с памяткой
Инкапсулируя Child с помощью memo, вы можете сделать m неизменным и не выполнять Child.В это время, пока значение m остается неизменным, компонент Child не будет выполняться.
Использование инкапсуляции React.memo вернет новый компонент и вызовет новый компонент
function Child(props){
console.log('child执行了')
return(
<div>
child:{props.data}
</div>
)
}
// 封装child
const Child2 = React.memo(Child)
ReactDOM.render(<App />,document.getElementById('root'));
Но на данный момент все еще есть ошибка: если к дочернему компоненту Child добавить функцию слушателя, то дочерний компонент будет выполняться независимо от того, изменено ли значение m или нет.
function App(){
const [n,setN] = useState(0);
const [m,setM] = useState(0);
const add=()=>{
setN(i=>i+1);
};
const addChild=()=>{
setM(i=>i+1);
};
+ const onClickChild=()=>{ };
return(
<div>
<div>
n:{n}
<button onClick={add}>n+1</button>
<button onClick={addChild}>m+1</button>
</div>
+ <Child2 data={m} onClick={onClickChild} />
</div>
)
}
function Child(props){
console.log('child执行了')
console.log('这里有很多代码')
return(
+ <div onClick={props.onClick}>
child:{props.data}
</div>
)
}
const Child2 = React.memo(Child)
При нажатии n код приложения будет выполнен повторно,onClickChild
Адрес пустой функции изменится, поэтому Child в это время все еще будет выполняться.
И Usememo решает эту проблему
Роль useMemo
Чтобы решить проблему рендеринга себя из-за обновления функции, вы можете использовать useMemo для переупаковки функции
const onClickChild=useMemo(fn,array)
Переменные монитора, первый параметр — функция, второй параметр — зависимость, функция будет пересчитана только при изменении зависимости
import React, { useMemo, useState } from 'react'
import ReactDOM from 'react-dom'
//其他的代码不变,只需要重写m的点击函数
//使用useMemo重新写监听函数,当m变化时才会执行此代码
const onClickChild=useMemo(()=>{
return ()=>{
console.log(m)
}
},[m])
Вы также можете заменить useMemo на useCallback, вам не нужно писать функцию возврата при использовании useCallback
const onClickChild=useMemo(()=>{
return ()=>{
console.log(m)
}
},[m])
//等价于
const onClickChild=useCallback(()=>{
console.log(m)
},[m])
Уведомление:
- Если ваше значение является функцией, вы должны написать
useMemo(()=>(x)=> console.log(x))
- Это функция, которая возвращает более сложную функцию, поэтому
useCallback
,вы можете использоватьuseCallback