Better

Ethan的博客,欢迎访问交流

Components, Hooks, and Performance

这是一篇译文,主要内容为 React 组件、Hook 和性能方面需要学习和注意的点,没有深入到各个细节,算是一个 Study List,原文分为 part1 和 part2,part1 比较基础,这里主要是 part2,链接可以在最后找到。

受控组件与非受控组件

简单来说,受控组件使用 state 进行管理,而非受控组件不关心值如何变化,使用 ref 获取 value 即可。具体看代码即可

class ControlledInput extends React.Component {
 state = {
   value: ""
 };

 onChange = (e) => this.setState({ value: e.target.value });

 render() {
   return (
     <input value={this.state.value} onChange={this.onChange}/>
   );
 }
}

class UncontrolledInput extends React.Component {
 input = React.createRef();

 getValue = () => {
   console.log(this.input.current.value);
 };

 render() {
   return (
     <input ref={this.input}/>
   );
 }
}

那么我们该如何选择呢?受控组件适合绝大多数场景,但也有例外,比如 file input,因为它的值是只读的,不能用代码进行设定,必须由用户进行交互。受控组件更加可读,能更友好的工作,比如即时的错误提示。

refs

refs 能获取到 Component 或 DOM Element 实例,应该尽量避免使用它,因为它会导致代码可读性变差,而且打破了 top-to-bottom 数据流。如果有更好的方式去解决问题,就要轻易使用它,比如提升状态或函数至父组件。

有三种方式

  • 使用字符串:避免使用,被淘汰
  • 在 ref 属性中使用回调函数
  • React.createRef()

如果想获得深层次的元素的时候,比如高阶组件中,我们就需要用到 React.forwardRef 进行 ref 转发

function withNewReference(Component) {
 class Hoc extends React.Component {
   render() {
     const {forwardedRef, ...props} = this.props;

     return <Component ref={forwardedRef} {...props}/>;
   }
 }

 return React.forwardRef((props, ref) => {
   return <Hoc {...props} forwardedRef={ref} />;
 });
}

错误边界

如果组件运行错误,如果父组件没有错误边界,会导致整个应用错误

class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    logToErrorLogger(error, info);
  }

  render() {
    if (this.state.hasError) {
      return <div>Help, something went wrong.</div>;
    }

    return this.props.children;
  }
}

HOC

想必你已经使用过 HOC 模式了,withNavigation, connect, withRouter 也是基于 HOC 的实现。

这里有一些使用高阶组件推荐做的和避免做的

  • 为 HOC 增加 display name
  • 不要在 render 函数中创建 HOC:你应该使用已经增强的组件,而不是在 render 中创建 HOC 组件,否则重新挂载会丢失当前 state
  • static 函数不会被复制,如果你需要的话,此时你需要手动复制
  • refs 不会传递,需要使用 React.forwardRef

styling

CRA 内置继承 CSS Modules,直接命名为 xxx.module.css 即可启用。

另一个解决有名的解决方案就是:CSS-in-JS。

hooks

hooks 是自重写依赖,最让人期待的特性了,这里就不说太多了,这是我近期学习的重点。

类型检查

在 React 15.5 后,PropTypes 作为一个独立的包需要独立安装,通过 static propTypes 指名类型,配合 defaultProps 属性声明默认参数,可以用来消除 PropTypes 产生的 warning。

另外的可选就是 Flow 和 TypeScript,如今 TypeScript 更加流行。

性能

最基础和明显的就是,你需要将 DefinePlugin 切换成 production,添加 UglifyJsPlugin,如果是 CRA 创建的项目,你只要运行 npm run build 即可。

针对 JS 文件,你可能会经历如下历程

  • 文件较少时,只需要 bundle.js
  • vendor + bundle
  • vendor + smallest required part + import things when they are needed.

介绍两个用来发现性能问题的工具

  • Chrome Performance Tab
  • DevTools Profiler

Code Splitting

主要使用 Webpack 提供的动态 import()

React.lazy() 实现懒加载,React.suspense() 在懒加载完成之前显示其他组件

来源



留言