学习Ref,forwardRef,useImperativeHandle
React.forwardRef
会创建一个React组件,这个组件能够将其接受的ref属性转发到其组件树下的另一个组件中;用于父组件操作子组件的DOM,也可以理解为子组件向父组件暴露 DOM 引用。
ref属性是React的特殊属性,不能直接使用。
如果想传递ref,需要借助forwardRef函数
常用情况:
(1)转发refs到DOM组件
(2)在高阶组件种转发refs
实例:
要实现父组件点击按钮,光标定位到子组件的输入框种,需要使用forwardRef,
useImperativeHandle(ref, createHandle, [deps])
,可以在使用ref时自定义暴露给父组件的实例值,减少暴露给父组件的属性,如以下只暴露focus方法,避免父组件操作整个input元素。
useMemo,useCallback和memo
useMemo
是一个用于性能优化的hook,避免在组件重新渲染时执行昂贵的计算;接受两个参数,一个函数和一个以来数字。当依赖数组种的值发生变化时,useMemo会重新计算并返回新的值,否则将返回上一次计算的值。
import React, { useMemo } from 'react';
const a = 1, b = 4;
function App() {
const result = useMemo(() => {
console.log(" calculation..." + a + "*" + b);
return a * b;
}, [a, b]);
return <div>Result: {result}</div>;
}
export default App;
ExpensiveComponent 接受两个属性 a 和 b 并使用 useMemo 钩子来计算 a 和 b 的乘积。当 a 或 b 发生变化时,useMemo 会重新计算结果。否则,它将返回上一次计算的值,避免了不必要的计算。
useCallback
也是用于优化性能的hook,帮助我们避免在组件重新渲染时创建新的函数实例。接受两个参数:一个函数和一个依赖数组。当依赖数组中的值发生变化时,useCallback会返回一个新的函数实例,否则则返回上一次创建的函数实例。
import React, { useCallback } from "react";
function ButtonComponent({ onClick, children }) {
return <button onClick={onClick}>{children}</button>;
}
function ParentComponent() {
const handleClick = useCallback(() => {
console.log("Button clicked");
}, []);
return (
<div>
<ButtonComponent onClick={handleClick}>Click me</ButtonComponent>
</div>
);
}
ButtonComponent 的组件,接受一个 onClick 函数属性。 ParentComponent使用 useCallback 钩子来创建一个 handleClick 函数。当 ParentComponent 重新渲染时,useCallback 会返回上一次创建的 handleClick 函数实例,避免了不必要的函数创建。
import React, { useCallback, memo } from 'react';
type ChildComponentProps = {
handleClick: () => void;
}
const ParentComponent = () => {
const handleClick = useCallback(() => {
console.log('Button clicked');
}, []); // 回调函数不依赖于任何值,因此只在组件首次渲染时创建
return <ChildComponent handleClick={handleClick} />;
};
const ChildComponent = React.memo<ChildComponentProps>(({ handleClick }) => {
console.log('ChildComponent rendered');
return <button onClick={handleClick}>Click me</button>;
});
function App() {
return <ParentComponent />;
}
export default App;
memo
是用于性能优化的高阶函数,避免在父组件重新渲染时重新渲染子组件。memo 接受一个组件作为参数,并返回一个新的组件。当新组件的属性发生变化时,它会重新渲染。否则,它将跳过渲染并返回上一次渲染的结果。
=> 我导说不对应该是这么说:memo 用于接收一个函数组件并将缓存后的组件返回,该组件的 props 未发生变化时组件不会重新执行
import React, { memo } from "react";
const ChildComponent = memo(function ChildComponent({ text }) {
console.log("ChildComponent rendered");
return <div>{text}</div>;
});
function ParentComponent({ showChild }) {
return (
<div>
{showChild && <ChildComponent text="Hello, world!" />}
<button onClick={() => setShowChild(!showChild)}>Toggle child</button>
</div>
);
}
ChildComponent 使用 memo 高阶组件对其进行了优化。 ParentComponent 可以切换 ChildComponent 的显示。当 ParentComponent 重新渲染时,ChildComponent 的属性没有发生变化,因此它不会重新渲染。