Skip to content

React是React库的入口。如果你通过使用<script>标签的方式来加载React,则可以通过React全局变量对象来获得React的顶层API。但你使用 es6与npm时,可以通过编写import React from 'react'来引入它们。当你使用ES5与npm时,则可以通过编写var React = require('react')来引入它们。

React顶层API

概览

组件

使用React组件可以将UI划分为独立且可复用的代码片段,每部分都可独立维护。你可以通过React.Component或者React.PureComponent来定义React组件。 如果你不使用ES6的class,则可以使用create-react-class模块来替代。

创建React元素

使用JSX来编写你的UI组件。每个JSX元素都是调用React.createElement()的语法糖。一般来说,如果你使用了JSX,就不需要调用以下方法了。

  • createElement()
  • createFactory()

转换元素

React提供了几个用于操作元素的API:

  • cloneElement()
  • isValidElement()
  • React.Children

Fragments

React还提供了用于减少不必要嵌套的组件

  • React.Fragment

Refs

  • React.createRef()
  • React.forwardRef()

Suspense

Suspense使得组件可以"等待"某些操作结束后,再进行渲染。目前,Suspense仅支持的使用场景是:通过React.lazy动态加载组件

  • React.lazy
  • React.Suspense

Hook

Hook是React 16.8的新增特性。它可以让你在不编写class的情况下使用state以及其他的React特性。

  • 基础Hook
    • useState
    • useEffect
    • useContext
  • 额外的Hook
    • useReducer
    • useCallback
    • useMemo
    • useRef
    • useImperativeHandle
    • useLayoutEffect
    • useDebugValue

参考

React.Component

React.Component是使用ES classes方式定义React组件的基类:

class Greeting extends React.Component{
    render(){
        return <h1>hello</h1>
    }
}

React.PureComponent

React.PureComponentReact.Component很相似。两者的区别在于React.Component并未实现shouldComponentUpdate(),而React.PureComponent中以浅层对比prop和state的方式来实现该函数。 如果赋予React组件相同的props和state,render()函数会渲染相同的内容,那么在某些情况下使用React.PureComponent可提高性能。

React.PureComponent中的shouldComponentUpdate仅作对象的浅层比较。如果对象中包含复杂的数据结果,则可能因为无法检查深层的差别,产生错误的比对结果。仅在你的props和state较为简单时,才使用React.PureComponent,或者在深层数据结果发生变化时调用forceUpdate()来确保组件被正确的更新。你也可以考虑使用immutable对象加速嵌套数据的比较。此外,React.PureComponent中的shouldComponentUpdate()将跳过所有子组件树的prop更新。因此,请确保所有的组件也都是"纯"的组件。

React.memo

    const MyComponent = React.memo(function MyComponent(props){})

React.memo高阶组件,它与React.PureComponent非常相似,但只适用于函数组件,而不适用于class组件, 如果你的函数组件给定相同的props的情况下渲染相同的结果,那么你可以通过将其包装在React.memo中调用,以此通过记忆组件渲染结果得方式来提高组件得性能表现。这意味着在这种情况下,React将跳过渲染组件的操作并直接复用最近一次渲染的结果。 React.memo仅检查props变更。如果函数组件被React.memo包裹,且其实现中拥有useStateuseContext的Hook,当context发生变化时,它仍然会重新渲染。 默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。

function MyComponent(props){}
function areEqual(prevProps,nextProps){
    /*
    如果把nextProps传入render方法得返回结果与将nextProps传入render方法返回结果返回一致则返回true,
    否则返回 false
    */
}
export default React.mome(MyComponent,areEqual)

此方法仅作为性能优化的方式而存在。但请不要依赖它来组织渲染,因为这会产生bug。

注意:与class组件中shouldComponentUpdate方法不同的是,如果props相等,areEqual会返回true;如果不相等,则返回false。这与shouldComponentUpdate方法的返回值相反。

createElement()

React.createElement(
    type,
    [props],
    [...children]
)

创建并返回指定类型得新React元素。其中的类型参数既可以是标签名字符串(如果divspan),也可以是React组件类型(class组件或函数组件),或是React Fragment类型。 使用JSX编写的代码将会转换成使用React.createElement()的形式。如果使用jsx方式,那么一般来说就不需要直接调用React.createElement()。请查阅不使用jsx。

cloneElement

React.cloneElement({
    element,
    [props],
    [...children]
})

element元素为样板克隆并返回新的React元素。返回元素的props是将新的props与原始元素的props浅层合并后的结果。新的子元素将取代现有的子元素,而来自原始的元素的keyref将被保留。 React.cloneElement几乎等同于:

<element.type {...element.props} {...props}>
{children}
</element.type>

但是,这也保留了组件的ref。这意味着当通过ref获取子节点时,你将不会意外地从你祖先节点上窃取它。相同地ref将添加到克隆后地新元素中。 引入此API是为了替换已经弃用地React.addons.cloneWithProps()

createFactory()

React.createFactory(type)

返回用于生成指定类型地React元素得函数。与React.createElement相似地是。类型参数既可以是标签名字符串。也可以是React组件类型,或是React Fragment类型。 此辅助函数已废弃,建议使用JSX或直接调用React.createElement来代替它。 如果你使用JSX,通常不会直接调用React.createFactory

isValidElement()

React.isValidElement(object)

验证对象是否为React元素,返回值为true或者false。

React.Children

React.Children提供了用于处理this.props.children不透明数据结构地实用方法。

React.Children.map

React.Children.map(children,function[(thisArg)])

children里每个直接子节点上调用一个函数,并将this设置为thisArg。如果children是一个数组。它将被遍历并为数组中地每个子节点调用该函数。如果子节点为null或是undefined,则此方法将返回null或者undefined,而不会返回数组。

注意:如果children是一个Fragment对象,它将被视为了一个单一节点地情况处理,而不会被遍历。

React.Children.forEach

React.Children.forEach(children,function[(thisArg)])

React.Children.map()类似,但它不会返回一个数组。

React.Children.count

React.Children.count(children)

返回children中组件的总数量,等同于通过mapforEach调用回调函数的次数。

React.Children.only

React.Children.only(children)

验证children是否只有一个子节点(一个React元素),如果有则返回它,否则此方法会抛出错误。

React.Children.toArray

React.Children.toArray(children)

children这个复杂的数据结构以数组的方式扁平开并返回,并为每个子节点分配一个key。当你想要在渲染函数中操作子节点的集合时,他会非常实用,特别是当你想要在向下传递this.props.children之前对内容重新排序或获取子集时。

React.Fragment

React.Fragment组件能够在不额外创建DOM元素的情况下,让render方法中返回多个元素。

    render(){
        return (
            <React.Fragment>
            Some text.
            <h2>A heading</h2>
            </React.Fragment>
        )
    }

你也可以实用其简写的语法<>< />

React.createRef

React.createRef创建一个能够通过ref属性附加到React元素的ref

    class MyComponent extends React.Component {
        constructor(props) {
            super(props);

            this.inputRef = React.createRef();
        }

        render() {
            return <input type="text" ref={this.inputRef}  />;
        }

        componentDidMount() {
            this.inputRef.current.focus();
        }
    }

React.forwardRef

React.forwardRef会创建一个React组件,这个组件能够将其接收的ref属性转发到其组件树下的另一个组件中。这种技术并不常见,但是以下两种场景中也别有用:

  • 转发refs到DOM组件
  • 在高级组件中转发refs React.forwardRef接收渲染函数作为参数。React将使用propsref作为参数来调用此函数。此函数应返回React节点。
    const FancyButton = React.forwardRef((props,ref)=>(
        <button ref={ref} className="FancyButton">
            {props.children}
        </button>
    ))
    const ref = React.createRef();
    <FancyButton ref={ref}>click me!</FancyButton>

在上述的示例中,React会将<FancyButton ref={ref}>元素的ref作为第二个参数传递给React.forwardRef函数中的渲染函数。该渲染函数会将ref传递给<button ref={ref}>元素。 因此,当React附加了ref属性之后,ref.current将直接指向<button>DOM元素实例。

React.lazy

React.lazy允许你定义一个动态加载的组件。这有助于缩减bundle的体积,并延迟加载在初次渲染时未用到的组件。 你可以在代码分割文档中学习如何使用它。

const SomeComponent = React.lazy(()=>import('./SomeComponent'));

请注意,渲染lazy组件依赖该组件渲染树上层的<React.Suspense>组件。这是指定加载指示器的方式。

注意:使用React.lazy的动态引入特性需要js环境支持Promise。在IE11及以下版本的浏览器中需要引入polyfill来使用该特性。

React.Suspense

React.Suspense可以指定加载指示器(loading indicator),以防其组件树中的某些子组件尚未具备渲染条件。目前,懒加载组件是<React.Suspense>支持的唯一用例:

    // 该组件是动态加载的
    const OtherComponent = React.lazy(() => import('./OtherComponent'));

    function MyComponent() {
    return (
        // 显示 <Spinner> 组件直至 OtherComponent 加载完成
        <React.Suspense fallback={<Spinner  />}>
        <div>
            <OtherComponent  />
        </div>
        </React.Suspense>
    );
    }

它已经被收录在我们的代码分割指南中。请注意,lazy组件可以位于Suspense组件树的深处 ———— 它不必包装树中的每一个延迟加载组件。最佳实践是将<Suspense>置于你想展示加载指示器的位置,而lazy()则可以被放置于任何你想要做代码分割的地方。 虽然目前尚未支持其他特性,但是未来我们计划让Suspense支持包括数据获取在内的更多场景。