React 知识总结

1. context

  1. 创建一个Context对象

const MyContext = React.createContext(defaultValue);

注意 : 将 undefined 传递给 Provider 时,消费组件的 defaultValue 不会生效。

  1. context.Provider



  • 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。

3.contextType


class MyClass extends React.Component {

  static contextType = MyContext;

  render() {

    let value = this.context;

    /* 基于这个值进行渲染工作 */

  }}

  //也可以在类的外部写成如下: Mycontext是在2中定义的

  My.contextType = Mycontext

  1. Context.Consumer



  { value => /* 基于 context 值进行渲染*/ }

  • 这里,React 组件也可以订阅到 context 变更。这能让你在函数式组件中完成订阅 context。

  • 这需要函数作为子元素(function as a child)这种做法。这个函数接收当前的 context 值,返回一个 React 节点。传递给函数的 value 值等同于往上组件树离这个 context 最近的 Provider 提供的 value 值。如果没有对应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue。

  1. 动态Context

import React from 'react';

const themes = {

    light: {

        color: 'blue',

        background: 'red',

    },

    dark: {

        color: '#ffffff',

        background: '#000000',

    },

};

const ThemeContext = React.createContext(

    themes.dark // 默认值

);

class ThemedButton extends React.Component {

    static contextType = ThemeContext;

    render() {

        let props = this.props;

        let theme = this.context;

        console.log(props,theme)

        return (

            

2.错误边界

1.注意错误边界无法捕获以下场景中产生的错误:

  • 事件处理(了解更多)

  • 异步代码(例如 setTimeout 或 requestAnimationFrame 回调函数)

  • 服务端渲染

  • 它自身抛出来的错误(并非它的子组件)


  1. 如果一个 class 组件中定义了 static getDerivedStateFromError() 或 componentDidCatch() 这两个生命周期方法中的任意一个(或两个)时,那么它就变成一个错误边界。当抛出错误后,请使用 static getDerivedStateFromError() 渲染备用 UI ,使用 componentDidCatch() 打印错误信息。

class ErrorBoundary extends React.Component {

  constructor(props) {

    super(props);

    this.state = { hasError: false };

  }

  static getDerivedStateFromError(error) { 

      // 更新 state 使下一次渲染能够显示降级后的 UI 

      return { hasError: true };

  } 

  componentDidCatch(error, info) { 

      // 你同样可以将错误日志上报给服务器   

      logErrorToMyService(error, info); 

  }

  render() { 

  if (this.state.hasError) {     

      // 你可以自定义降级后的 UI 并渲染     

      return 

Something went wrong.

; } return this.props.children; }}

Refs转发

定义 :Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧。对于大多数应用中的组件来说,这通常不是必需的。但其对某些组件,尤其是可重用的组件库是很有用的。最常见的案例如下所述。


  1. 何时使用Refs
  • 管理焦点,文本选择或媒体播放。

  • 触发强制动画。

  • 集成第三方 DOM 库


  1. 创建Refs:Refs 是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。

class MyComponent extends React.Component {

  constructor(props) {

        super(props);   

        this.myRef = React.createRef();

    }

  render() { 

  return 
; } }

  1. 访问Refs:当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。

const node = this.myRef.current;


  1. ref 的值根据节点的类型而有所不同:
  • 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。

  • 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。

  • 你不能在函数组件上使用 ref 属性,因为他们没有实例。

Fragments

  1. 定义:Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。

< Fragments > < /Fragments > 或者<>

高阶组件

  1. 定义:高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。

  1. 高阶组件是参数为组件,返回值为新组件函数

  1. 注意:HOC 不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC 通过将组件包装在容器组件中来组成新组件。HOC 是纯函数,没有副作用。

  1. 虽然高阶组件的约定是将所有 props 传递给被包装组件,但这对于 refs 并不适用。那是因为 ref 实际上并不是一个 prop - 就像 key 一样,它是由 React 专门处理的。如果将 ref 添加到 HOC 的返回组件中,则 ref 引用指向容器组件,而不是被包装组件。

深入JSX

  1. 实际上,JSX 是 React.createElement(component, props, ...children) 函数的语法糖。

  1. 大写字母开头的 JSX 标签意味着它们是 React 组件。这些标签会被编译为对命名变量的直接引用,所以,当你使用 JSX 表达式时,Foo 必须包含在作用域内。

  1. 如果你没给 prop 赋值,它的默认值是 true



//这俩表达式完全等价




  1. 如果你已经有了一个 props 对象,你可以使用展开运算符... 来在 JSX 中传递整个 props 对象

function App1() {

  return ;}

function App2() {

  const props = {firstName: 'Ben', lastName: 'Hector'};

  return ;

  }


  1. false, null, undefined, and true 是合法的子元素。但它们并不会被渲染。以下的 JSX 表达式渲染结果相同;

  1. 值得注意的是有一些 “falsy” 值,如数字 0,仍然会被 React 渲染。例如,以下代码并不会像你预期那样工作,因为当 props.messages 是空数组时,0 仍然会被渲染:

{props.messages.length && }

要解决这个问题,确保 && 之前的表达式总是布尔值:


{props.messages.length > 0 && }

反之,如果你想渲染 false、true、null、undefined 等值,你需要先将它们转换为字符串:


My JavaScript variable is {String(myVariable)} .

性能优化

  1. 确保你正在使用压缩后的生产版本

  2. Immutable.js

  3. 更多请自行百度

Portals

定义:Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。


  1. 第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。

ReactDOM.createPortal(child, container)

  1. 通常来讲,当你从组件的 render 方法返回一个元素时,该元素将被挂载到 DOM 节点中离其最近的父节点:

render() {

  // React 挂载了一个新的 div,并且把子元素渲染其中

      return ( 

      
{this.props.children}
); }
然而,有时候将子元素插入到 DOM 节点中的不同位置也是有好处的:

render() {

  // React 并*没有*创建一个新的 div。它只是把子元素渲染到 `domNode` 中。

  // `domNode` 是一个可以在任何位置的有效 DOM 节点。

  return ReactDOM.createPortal(

    this.props.children,    domNode

  );

}

一个 portal 的典型用例是当父组件有 overflow: hidden 或 z-index 样式时,但你需要子组件能够在视觉上“跳出”其容器。例如,对话框、悬浮卡以及提示框:

使用 PropTypes 进行类型检查

  1. 注意 : 自 React v15.5 起,React.PropTypes 已移入另一个包中。请使用 prop-types 库 代替。

  2. 使用方法


import PropTypes from 'prop-types';

class Greeting extends React.Component {

  render() {

    return (

      

Hello, {this.props.name}

); } } Greeting.propTypes = { name: PropTypes.string };

import PropTypes from 'prop-types';

MyComponent.propTypes = {

  // 你可以将属性声明为 JS 原生类型,默认情况下

  // 这些属性都是可选的。

  optionalArray : PropTypes.array,

  optionalBool : PropTypes.bool,

  optionalFunc : PropTypes.func,

  optionalNumber : PropTypes.number,

  optionalObject : PropTypes.object,

  optionalString : PropTypes.string,

  optionalSymbol : PropTypes.symbol,

  // 任何可被渲染的元素(包括数字、字符串、元素或数组)

  // (或 Fragment) 也包含这些类型。

  optionalNode : PropTypes.node,

  // 一个 React 元素。

  optionalElement : PropTypes.element,

  // 一个 React 元素类型(即,MyComponent)。

  optionalElementType : PropTypes.elementType,

  // 你也可以声明 prop 为类的实例,这里使用

  // JS 的 instanceof 操作符。

  optionalMessage : PropTypes.instanceOf(Message),

  // 你可以让你的 prop 只能是特定的值,指定它为

  // 枚举类型。

  optionalEnum : PropTypes.oneOf(['News', 'Photos']),

  // 一个对象可以是几种类型中的任意一个类型

  optionalUnion : PropTypes.oneOfType([

    PropTypes.string,

    PropTypes.number,

    PropTypes.instanceOf(Message)

  ]),

  // 可以指定一个数组由某一类型的元素组成

  optionalArrayOf: PropTypes.arrayOf(PropTypes.number),

  // 可以指定一个对象由某一类型的值组成

  optionalObjectOf: PropTypes.objectOf(PropTypes.number),

  // 可以指定一个对象由特定的类型值组成

  optionalObjectWithShape: PropTypes.shape({

    color: PropTypes.string,

    fontSize: PropTypes.number

  }),



  // An object with warnings on extra properties

  optionalObjectWithStrictShape: PropTypes.exact({

    name: PropTypes.string,

    quantity: PropTypes.number

  }), 

  // 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保

  // 这个 prop 没有被提供时,会打印警告信息。

  requiredFunc: PropTypes.func.isRequired,

  // 任意类型的数据

  requiredAny: PropTypes.any.isRequired,

  // 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。

  // 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。

  customProp: function(props, propName, componentName) {

    if (!/matchme/.test(props[propName])) {

      return new Error(

        'Invalid prop `' + propName + '` supplied to' +

        ' `' + componentName + '`. Validation failed.'

      );

    }

  },

  // 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。

  // 它应该在验证失败时返回一个 Error 对象。

  // 验证器将验证数组或对象中的每个值。验证器的前两个参数

  // 第一个是数组或对象本身

  // 第二个是他们当前的键。

  customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {

    if (!/matchme/.test(propValue[key])) {

      return new Error(

        'Invalid prop `' + propFullName + '` supplied to' +

        ' `' + componentName + '`. Validation failed.'

      );

    }

  })};

React.Component

  1. render() 方法是 class 组件中唯一必须实现的方法。

  2. constructor()

如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。

  1. 通常,在 React 中,构造函数仅用于以下两种情况:
  • 通过给 this.state 赋值对象来初始化内部 state。

  • 为事件处理函数绑定实例


  1. 在 constructor() 函数中不要调用 setState() 方法。如果你的组件需要使用内部 state,请直接在构造函数中为 this.state 赋值初始 state

constructor(props) {

  super(props);

  // 不要在这里调用 this.setState()

  this.state = { counter: 0 };

  this.handleClick = this.handleClick.bind(this);

}


  1. 避免将 props 的值复制给 state!这是一个常见的错误:

componentDidMount()钩子

  1. 调用时机以及主要作用
  • componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。

  • 依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。

componentDidUpdate(prevProps, prevState, snapshot)

  1. componentDidUpdate() 会在更新后会被立即调用。首次渲染不会执行此方法。

  2. 你也可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语件里,否则会导致死循环。

  3. 注意 : 如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate()。

componentWillUnmount()

  • componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。

  • componentWillUnmount() 中不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

shouldComponentUpdate(nextProps, nextState) 不常用

  1. 此方法仅作为性能优化的方式而存在。不要企图依靠此方法来“阻止”渲染,因为这可能会产生 bug。你应该考虑使用内置的 PureComponent 组件,而不是手动编写

  2. 首次渲染或使用 forceUpdate() 时不会调用该方法。

  3. 返回值默认为true , 若为false则不渲染该组件,但子组件的state变化依旧会进行渲染子组件

static getDerivedStateFromProps(props, state)

调用时机 : 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state(相当于merge),如果返回 null则不更新任何内容。

getSnapshotBeforeUpdate(prevProps, prevState)

  1. 调用时机 : getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。

static getDerivedStateFromError(error)

此生命周期会在后代组件抛出错误后被调用。 它将抛出的错误作为参数,并返回一个值以更新 state


class ErrorBoundary extends React.Component {

  constructor(props) {

    super(props);

    this.state = { hasError: false };

  }

  static getDerivedStateFromError(error) { 

      // 更新 state 使下一次渲染可以显降级 UI 

      return { hasError: true };

  }

  render() { 

  if (this.state.hasError) {   

      // 你可以渲染任何自定义的降级  UI   

      return 

Something went wrong.

; } return this.props.children; }}

componentDidCatch(error, info)

此生命周期在后代组件抛出错误后被调用。 它接收两个参数:

  • error —— 抛出的错误

  • info —— 带有 componentStack key 的对象,其中包含有关组件引发错误的栈信息。

setState()

  1. 这个是异步的 , 如果想再一次回调中执行多次setState(),请使用回调函数的方式或者componentDidUpdate

  2. 除非 shouldComponentUpdate() 返回 false,否则 setState() 将始终执行重新渲染操作。

  3. 函数式setState


this.setState((state, props) => {

    return { counter: state.counter + props.step };

  }

);

  1. 直接赋值式

this.setState({quantity: 2})

forceUpdate(callback)

  • 默认情况下,当组件的 state 或 props 发生变化时,组件将重新渲染。如果 render() 方法依赖于其他数据,则可以调用 forceUpdate() 强制让组件重新渲染。

  • 调用 forceUpdate() 将致使组件调用 render() 方法,此操作会跳过该组件的 shouldComponentUpdate()。但其子组件会触发正常的生命周期方法,包括 shouldComponentUpdate() 方法。如果标记发生变化,React 仍将只更新 DOM。

defaultProps

defaultProps 可以为 Class 组件添加默认 props。这一般用于 props 未赋值,但又不能为 null 的情况。例如:


class CustomButton extends React.Component {

  // ...

  }

CustomButton.defaultProps = {

  color: 'blue'

  };

如果未提供 props.color,则默认设置为 'blue'


  render() {

    return  ;

    // props.color 将设置为 'blue'

  }

如果 props.color 被设置为 null,则它将保持为 null


  render() {

    return  ;

    // props.color 将保持是 null

  }

ReactDOM

如果你使用一个

你可能感兴趣的:(React 知识总结)