在父组件中嵌套子组件 父组件更新 导致子组件也重新渲染
父组件
在父组件中嵌套了子组件 子组件的作用也很单纯 就只有渲染 一个 h3 标题
import { useState } from 'react';
import Son from './Son';
export default function Father() {
const [count, setCount] = useState(0);
return (
<>
<div>
<h2>父组件</h2>
<h2>{count}</h2>
<button onClick={() => setCount(count + 1)}>+1</button>
<hr />
<Son />
</div>
</>
);
}
子组件
export default function Son() {
console.log('render...');
return (
<>
<div>
<h3>子组件</h3>
</div>
</>
);
}
当在父组件中点击累加的时候 父组件重新渲染 导致了子组件也跟着重新渲染 这样对性能的损耗是很大的 当子组件中逻辑较多的时候 父组件每当重新渲染 子组件中的逻辑都会跟着重新执行
memo的使用
使用 memo 对其进行优化
子组件
import { memo } from 'react';
export default memo(() => {
console.log('render...');
return (
<>
<div>
<h3>子组件</h3>
</div>
</>
);
});
此时我们发现 子组件在使用 memo 包裹之后 子组件的内容不会跟着重新渲染了
需求:在子组件中 处理父组件累加的事件
父组件
import { useState } from 'react';
import Son from './Son';
export default function Father() {
const [count, setCount] = useState(0);
// 在父组件中写好累加的函数 将这个函数传递给子组件 子组件调用就好了
const handleCount = () => setCount(count + 1);
return (
<>
<div>
<h2>父组件</h2>
<h2>{count}</h2>
<hr />
<Son handleCount={handleCount} />
</div>
</>
);
}
子组件
import { memo } from 'react';
type TProps = {
handleCount: () => void;
};
export default memo(({ handleCount }: TProps) => {
console.log('render...');
<img src=" " alt="" width="50%" />
return (
<>
<div>
<h3>子组件</h3>
{/* 子组件直接调用父组件传递的累加函数 */}
<button onClick={() => handleCount()}>click</button>
</div>
</>
);
});
又发现了新的问题 memo 失效了 ???
useCallback的使用
在写 handleCount 函数时需要注意的点 函数 函数 我们可能会写成下面这样
// 错误写法
const handleCount = () = useCallback(() => setCount(count + 1), []);
// 正确写法
const handleCount = useCallback(() => setCount(count + 1), []);
// [] 数组为空表示 不检测数据更新
const xxx = useCallback(() => {}, [])
父组件
import { useCallback, useState } from 'react';
import Son from './Son';
export default function Father() {
const [count, setCount] = useState(0);
const handleCount = useCallback(() => setCount(count + 1), []);
return (
<>
<div>
<h2>父组件</h2>
<h2>{count}</h2>
<hr />
<Son handleCount={handleCount} />
</div>
</>
);
}
这个时候会发现一个问题 count 的值到1就加不动了
解决方式 setCount(count + 1) --> setCount((count) => count + 1) 不断使用新值覆盖旧值
父组件
import { useCallback, useState } from 'react';
import Son from './Son';
export default function Father() {
const [count, setCount] = useState(0);
const handleCount = useCallback(() => setCount((count) => count + 1), []);
return (
<>
<div>
<h2>父组件</h2>
<h2>{count}</h2>
<hr />
<Son handleCount={handleCount} />
</div>
</>
);
}
在使用 useCallback 后 子组件不会跟着重新渲染了 控制台没有重复打印 render
父组件传递数据给组件时
父组件
import { useCallback, useState } from 'react';
import Son from './Son';
export default function Father() {
const [count, setCount] = useState(0);
const obj = {
name: '张三',
age: 20,
};
const handleCount = useCallback(() => setCount((count) => count + 1), []);
return (
<>
<div>
<h2>父组件</h2>
<h2>{count}</h2>
<hr />
<Son handleCount={handleCount} obj={obj} />
</div>
</>
);
}
子组件
import { memo } from 'react';
type TProps = {
handleCount: () => void;
obj: {
name: string;
age: number;
};
};
export default memo(({ handleCount, obj }: TProps) => {
console.log('render...');
return (
<>
<div>
<h3>子组件</h3>
{/* 子组件直接调用父组件传递的累加函数 */}
<button onClick={() => handleCount()}>click</button>
<hr />
<h3>
父组件传递的值为:{obj.name} --- {obj.age}
</h3>
</div>
</>
);
});
此时又发现新的问题了 传递数据时 子组件也跟着重新渲染了
useMemo的使用
父组件
import { useCallback, useMemo, useState } from 'react';
import Son from './Son';
export default function Father() {
const [count, setCount] = useState(0);
const obj = {
name: '张三',
age: 20,
};
const handleCount = useCallback(() => setCount((count) => count + 1), []);
const sendObj = useMemo(() => {
return {
...obj,
};
}, []);
return (
<>
<div>
<h2>父组件</h2>
<h2>{count}</h2>
<hr />
<Son handleCount={handleCount} obj={sendObj} />
</div>
</>
);
}
在使用了 useMemo 将数据包裹后 传递给子组件 控制台没有重新渲染 重复打印 render 了