React基础与实践 | 青训营笔记

28 阅读2分钟

特性

image.png

实战

划分组件

  1. ui组件:有明显的ui显示功能,易于区分和划分。

  2. 服务于组件的组件:没有ui显示,但有一些支持功能。

    1. 例如,几个相似背景+主体的模块,可以拆分一个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

性能优化

  1. useCallback

    返回一个回调函数。

    当依赖项改变时才更新函数。(依赖项为空呢,永远不会更新,函数作用域永远为初始化时那个)

    useCallbak搭配shouldComponentUpdate 和 React.memo使用。 比如子组件是一个memo组件,传给子组件一个callback函数就尽量是useCallback包装后的,这样就不会父组件重渲——生成新的回调函数——memo子组件发现props变化——子组件重渲。

  2. useMemo

    返回一个值。

    当依赖项改变时才重新计算值。(没有依赖项,每次渲染都重新计算)

    适合用于有大量计算逻辑的情况。

    useMemo或useCallback有生成新函数——比较依赖项的开销,只是如果比较结果为相同,不将新的值赋给原变量。

  3. 使用场景

    场景一:大量计算

    重构的解决方案:

    把频繁更新和不需要频繁更新(或需要大量计算的)的逻辑分开,拆成两个子组件。

    场景二:组件的props为引用类型

  4. React.memo

    props浅层比较

组件挂载位置

  1. react-dom的api,createPortal

  2. 冒泡问题:

    1. 真实渲染位置(no) or 代码书写位置(yes)
    2. 从protal内部触发的事件会冒泡到React树的祖先