成为高级 React 开发你需要知道的知识点

250 阅读3分钟
原文链接: www.jianshu.com

简评:除了常见的 HOC 和 RenderProp 技巧,作者介绍了 7 个有用的知识点。

使用 Fragment 而不是 div

很多时候我们想要处理多个 component,但是 render 只允许返回一个 component,为了处理这个问题很可以使用 <div /> 标签来包装所有的 component 。但这会添加额外的 HTML 元素。所以官方的建议是推荐使用 React Fragments 来处理这个问题

import React, { Fragment } from 'react';

function ListItem({ item }) {
  return (

    <Fragment>
      <dt>{item.term}</dt>
      <dd>{item.description}</dd>
    </Fragment>

    // 也可以使用 <>....</> 来替换 <Fragment>
    // 等同于
    // <>
    //  <dt>{item.term}</dt>
    //  <dd>{item.description}</dd>
    // </>   

  );
}

function Glossary(props) {
  return (
    <dl>
      {props.items.map(item => (
        <ListItem item={item} key={item.id} />
      ))}
    </dl>
  );
}

context 用起来

Context 提供了一种方式将数据传递到整个 component 树中,而不必手动为每一层 component 传递 props。

因此,如果你有多个需要值的 component,建议使用 context。如果只有一个子 component 需要使用这个值建议使用 compositions

最少使用一个 Error Boundaries

React 16 附带了一个惊艳的功能 Error Boundaries。使用 Error Boundaries 我们可以处理这种问题,子组件出现错误不会导致整个应用报错和白屏。

举个例子: 定义一个 ErrorBoundary 组件

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }
componentDidCatch(error, info) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, info);
  }
render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
return this.props.children; 
  }
}

用法和其他组件一样简单:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

注意:React15 中的 unstable_handleError 方法不再有效,需要替换成 componentDidCatch 方法。

在生产环境中使用 production build

官网提供了很多提高性能的 配置。只需要 10 分钟即可给你的应用带来质的飞跃,在部署到生产环境前别忘了检查它们。

使用 Refs 来操纵元素

我们可以使用 Refs 来触发动画,文本选择或焦点管理。

例如:

我们可以 获取 inpout DOM 节点引用

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // Create a ref to store the textInput DOM element
    this.textInput = React.createRef();
  }
  render() {
  // Use the `ref` callback to store a reference to the text input DOM
  // element in an instance field (for example, this.textInput).
    return (
      <input
        type="text"
        ref={this.textInput}
      />
    );
  }
}

然后就可以在合适的时机聚焦这个 <input />

focus() {
  // Explicitly focus the text input using the raw DOM API
  // Note: we're accessing "current" to get the DOM node
  this.textInput.current.focus();
}

使用代码拆分

如果你使用 create-react-app 创建应用或使用 NextJs 会自动创建一个 webpack 配置文件,webpack 会将整个应用打包到一个文件中,如果应用程序变得复杂或者添加第三方库都会导致最终生成的文件变大,导致应用访问速度变慢。这时候可以使用代码拆分,创建多个输出,在需要的时候才加载对应的包,可以大大改善网页加载时间。

可以使用 React.lazy 来实现代码拆分。

使用方式也很简单,这里简单实现一个基于路由代码分割的例子:

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

注意: React.lazy 和 Suspense 暂不支持服务端渲染,如果服务端渲染想要实现这个功能可以使用 React Loadable

静态类型检查

JavaScript 不会对类型进行检查,这可能导致很多的问题。可以使用类型检查器(例如 Flow)来帮助我们提前发现错误。Flow 是有 facebook 开发的类型检查器,可以给变量、函数和 React Component 添加而外的注释是一个不错的选择。


原文链接:Concepts to become an advanced React developer
推荐阅读:改进 GitHub 工作流的 15 个建议