Advanced Guide to Reaction

react advancement

Lazy load

React.lazyFunctions allow you to handle dynamic imports like rendering regular components.
SuspenseLoad indicators elegantly degrade components.
fallbackProperty accepts whatever you want to show during component loading React Elements.

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

function MyComponent() {
  return (
    <div>
      <Suspense fallback={<div>Loading...</div>}>
        <OtherComponent />
      </Suspense>
    </div>
  );
}

Context

Context provides a way to transfer data between component trees without manually adding props to each layer of components. It is designed to share data that is "global" to a component tree.

// Context allows us to pass values deep into the component tree without explicitly passing them through each component.
// Create a context for the current theme ("light" is the default).
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // Use a Provider to pass the current theme to the following component tree.
    // No matter how deep, any component can read this value.
    // In this example, we pass "dark" as the current value.
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// The middle component no longer has to specify that the theme is passed down.
function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // Specify contextType to read the current theme context.
  // React finds the nearest theme Provider up and uses its value.
  // In this example, the current theme value is "dark".
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

Use cautiously, as this can make components less reusable.

API:

React.createContext:
Create a Context object. When React renders a component that subscribes to the Context object, the component reads the current context value from the matching Provider closest to itself in the component tree. The defaultValue parameter of a component will only take effect if it is not matched to the Provider in the tree in which it is located.

Context.Provider:
Each Context object returns a Provider React component that allows the consumer component to subscribe to context changes. When the value value of the Provider changes, all the consuming components within it will be re-rendered.

Class.contextType:
The contextType attribute mounted on the class is reassigned to a Context object created by React.createContext(). This allows you to use this.context to consume the value on the latest Context. You can access it in any lifecycle, including render functions.

Context.Consumer:
Here, React components can also subscribe to context changes. This allows you to subscribe to context in functional components.

Refs

Refs provides a way to access DOM nodes or React elements created in render methods. ref attributes cannot be used on function components because they have no instances and can be used inside function components.

Suitable for refs:

  • Manage focus, text selection or media playback.
  • Trigger mandatory animation.
  • Integrate third-party DOM libraries.

Usage method:

  1. Create Refs

    • Refs are created using React.createRef() and attached to React elements through the ref attribute.
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}
  1. Visit Refs

    • Accessed in ref's current attribute
const node = this.myRef.current;

Refs forwarding

Ref forwarding is a technique for automatically passing ref through a component to one of its subcomponents. Subcomponents receive refs using React.forwardRef. It can be used for Hoc processing Ref.

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can get the ref of DOM button directly:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

In the example above, FancyButton uses React. forward Ref to get the ref passed to it and forward it to the DOM button it renders. In this way, components using FancyButton can retrieve the ref of the underlying DOM node button and access it if necessary, just as they use DOM button directly.

Fragments

Fragments allows you to group sublists without adding additional nodes to the DOM. key is the only attribute that can be passed to Fragment

render() {
  return (
    <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
    </React.Fragment>
  );
}

<React.Fragment> </React.Fragment> can be abbreviated as <> </>.

High Order Component (HOC)

HOC is a function whose parameters are components and whose return values are new components.

HOC does not modify incoming components or use inheritance to copy their behavior. Instead, HOC forms new components by wrapping components in container components. HOC is a pure function with no side effects.

Examples:

// This function receives a component...
function withSubscription(WrappedComponent, selectData) {
  // ... and returns another component...
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    componentDidMount() {
      // Responsible for subscription related operations.
      DataSource.addChangeListener(this.handleChange);
    }

    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }

    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }

    render() {
      // ... and use new data to render packaged components!
      // Note that we may pass other attributes as well.
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

In the example above, the class component is the container component of HOC. The container component takes the responsibility of separating the high-level and low-level concerns. The container manages subscriptions and states, and passes prop to the processing and rendering UI. HOC uses containers as part of its implementation, and you can consider HOC as a parameterized container component.

Matters needing attention:

  • Do not use HOC in render methods.

    Using diff algorithm in render will cause different detection when comparing component changes. Unloading and reloading operations will be performed every time rendering. This is not only a performance problem - reloading component will result in loss of state of the component and all its subcomponents.

  • Be sure to copy static methods to container components.

    All non-React static methods can be automatically copied using hoist-non-react-statistics

    import hoistNonReactStatic from 'hoist-non-react-statics';
    function enhance(WrappedComponent) {
      class Enhance extends React.Component {/*...*/}
      hoistNonReactStatic(Enhance, WrappedComponent);
      return Enhance;
    }
  • Refs will not be delivered.

    Available through Refs Forwarding Solution

Common HOC:

Connection of redux

React.PureComponent

In most cases, you can use React.PureComponent instead of handwritten shouldComponentUpdate. Only when the detected data are arrays or objects, because of the problem of shallow copy, the comparison will be deviated and can not be used. At this time, the use of deep copy can continue to be used.

As follows:

class CounterButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (this.props.color !== nextProps.color) {
      return true;
    }
    if (this.state.count !== nextState.count) {
      return true;
    }
    return false;
  }

  render() {
    return (
      <button
        color={this.props.color}
        onClick={() => this.setState(state => ({count: state.count + 1}))}>
        Count: {this.state.count}
      </button>
    );
  }
}

It can be replaced by:

class CounterButton extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {count: 1};
  }

  render() {
    return (
      <button
        color={this.props.color}
        onClick={() => this.setState(state => ({count: state.count + 1}))}>
        Count: {this.state.count}
      </button>
    );
  }
}

Portals

Portal provides an excellent solution for rendering child nodes to DOM nodes that exist outside the parent component.

A typical use case for portal is when the parent component has an overflow: hidden or z-index style, but you need the child component to be able to visually "jump" out of its container. For example, dialog boxes, suspension cards and prompt boxes:

render() {
  // React and * NO * create a new div. It just renders the child elements into `domNode'.
  // ` domNode` is a valid DOM node that can be located anywhere.
  return ReactDOM.createPortal(
    this.props.children,
    domNode
  );
}

React.StrictMode

StrictMode does not render any visible UI. It triggers additional checks and warnings for its descendant elements. Strict pattern checks run only in development mode; they do not affect production builds.

Effect:
  • Identifying unsafe life cycles
  • Warning about using the obsolete string ref API
  • Warning about using the discarded find DOMNode method
  • Detection of unintended side effects
  • Detecting obsolete context API s

Original git address If it's helpful, star t and keep updating.

Tags: Javascript React Fragment Attribute less

Posted on Thu, 08 Aug 2019 02:18:20 -0700 by rklapwijk