特性
实战
划分组件
-
ui组件:有明显的ui显示功能,易于区分和划分。
-
服务于组件的组件:没有ui显示,但有一些支持功能。
- 例如,几个相似背景+主体的模块,可以拆分一个BlockWrapper组件,进行背景、动画等设置。
通信
父 to 子
如果父组件需要给多个子组件传递props,每个都传递过于复杂,可以遍历子组件,使用cloneElement统一传递props。
<div>
{React.Children.map(children, (child) => {
if (child && child.props) {
return React.cloneElement(child, commonProps);
}
return child;
})}
</div>
子 to 父
父组件调用子组件的方法,使用ref转发,将方法挂在ref上,ref是一个承载介质。
const FormComponent = (props, ref) => {
useImperativeHandle(ref, () => ({
submit: () => {
alert('submit');
}
}));
return (
<form>
<input type="text" />
</form>
)
}
const FormComponentWithRef = forwardRef(FormComponent);
简单示例: 子组件接收ref,使用useImperativeHandle挂载方法,使用forwardRef生成包装后的组件。 父组件使用包装后的组件,并将ref传递给该组件。
组件间 context reducer
略
性能优化
-
useCallback
返回一个回调函数。
当依赖项改变时才更新函数。(依赖项为空呢,永远不会更新,函数作用域永远为初始化时那个)
useCallbak搭配shouldComponentUpdate 和 React.memo使用。 比如子组件是一个memo组件,传给子组件一个callback函数就尽量是useCallback包装后的,这样就不会父组件重渲——生成新的回调函数——memo子组件发现props变化——子组件重渲。
-
useMemo
返回一个值。
当依赖项改变时才重新计算值。(没有依赖项,每次渲染都重新计算)
适合用于有大量计算逻辑的情况。
useMemo或useCallback有生成新函数——比较依赖项的开销,只是如果比较结果为相同,不将新的值赋给原变量。
-
使用场景
场景一:大量计算
重构的解决方案:
把频繁更新和不需要频繁更新(或需要大量计算的)的逻辑分开,拆成两个子组件。
场景二:组件的props为引用类型
-
React.memo
props浅层比较
组件挂载位置
-
react-dom的api,createPortal
-
冒泡问题:
- 真实渲染位置(no) or 代码书写位置(yes)
- 从protal内部触发的事件会冒泡到React树的祖先