Heaven and earth move! React can also use the computed attribute

Foreword, about calculation properties

The first time I saw the word calculation property was in the official Vue document Calculation properties and listeners In the section, the article describes the calculation attributes as follows:

Expressions in templates are very convenient, but they are designed for simple operations. Putting too much logic in a template makes it too heavy and difficult to maintain.

Looking back at the React code we wrote, is there too much logic in JSX (render function) that makes render function too large and difficult to maintain?

Calculation properties in React

Before we talk about React, let's take a look at Vue. In Vue, calculation properties mainly have the following two characteristics:

  1. The calculation property creates a dependency in a declarative way, and the changes of dependent data or props will trigger recalculation and automatic update.
  2. Calculated properties are cached based on their responsive dependencies.

In React, the calculation attributes are often visible. I believe that readers familiar with React have written similar codes as follows:

import React, { Fragment, Component } from 'react';

class Example extends Component {
  state = {
    firstName: '',
    lastName: '',
  };

  render() {
    // Handling logic in the render function
    const { firstName, lastName } = this.state;
    const fullName = `${firstName} ${lastName}`;
    return <Fragment>{fullName}</Fragment>;
  }
}

In the above code, fullName in the render function depends on firstName and lastName in props. After the firstName or lastName changes, the variable fullName is automatically updated. The implementation principle is that the change of props and state will cause the render function to call, and then recalculate the derived value.

Although we can implement computation, but we still put the computation logic into the render function, which leads to its bloated, which is not elegant. The better way is to extract the calculation logic and simplify the render function logic:

class Example extends Component {
  state = {
    firstName: '',
    lastName: '',
  };

  // The logic in render is taken as a function to reduce the overstaffing of render function
  renderFullName() {
    const { firstName, lastName } = this.state;
    return `${firstName} ${lastName}`;
  }

  render() {
    const fullName = this.renderFullName();
    return <Fragment>{fullName}</Fragment>;
  }
}

If you know Vue well, you must know its computed calculation property. The underlying layer is the getter, just the getter of the object. In React, we can also use the getter of the class to implement the calculation property:

class Example extends Component {
  state = {
    firstName: '',
    lastName: '',
  };

  // Reduce variables by getter instead of function
  get fullName() {
    const { firstName, lastName } = this.state;
    return `${firstName} ${lastName}`;
  }

  render() {
    return <Fragment>{this.fullName}</Fragment>;
  }
}

Further, use memoization to optimize calculation attributes

As mentioned above, in Vue, there will be caching to reduce the calculation. Because a calculated property will only be re evaluated if its related dependency changes.

This means that as long as the firstName and lastName have not changed, multiple accesses to the fullName calculation property will immediately return the previous calculation results without executing the function again.

By contrast, does React's getter have the advantage of caching??? The answer is: No. The getter in React does not do cache optimization!

But don't be disappointed, we can use the memory technology to optimize our computing properties to achieve the same effect as the computing properties in Vue. We need to introduce the memo one library into the project. The code is as follows:

import memoize from 'memoize-one';
import React, { Fragment, Component } from 'react';

class Example extends Component {
  state = {
    firstName: '',
    lastName: '',
  };

  // If it is the same as the last parameter, 'remember one' will reuse the last value.
  getFullName = memoize((firstName, lastName) => `${firstName} ${lastName}`);

  get fullName() {
    return this.getFullName(this.state.firstName, this.state.lastName);
  }

  render() {
    return <Fragment>{this.fullName}</Fragment>;
  }
}

Further, use React Hooks to optimize calculation properties

The memory one library is used in React to achieve the effect similar to Vue computed, which is based on the result of dependency cache. Thanks to the new Hooks feature of React 16.8, we can encapsulate the logic more elegantly. For those who don't know enough about Hooks, please read another article of our team After reading this, you can also play React Hooks

Here, we need to use useMemo. The official introduction of useMemo is in Here , please check for details. Simply put, we pass in a callback function and a dependency list. React will call the callback function when the value in the dependency list changes, and cache the result returned by the callback function:

import React, { useState, useMemo } from 'react';

function Example(props) {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  // Using the useMemo function to cache the calculation process
  const renderFullName = useMemo(() => `${firstName} ${lastName}`, [
    firstName,
    lastName,
  ]);

  return <div>{renderFullName}</div>;
}

summary

This paper introduces how to realize the effect similar to Vue computed in React, which is based on the result of dependent cache computing, to realize the decoupling of logical computing and view rendering, and reduce the complexity of render function.

From the perspective of business development, the API provided by Vue greatly improves the development efficiency. In some scenarios, React does not have the support of the official native API of the same kind, but thanks to the active community, the problems encountered in the work can always find solutions. While exploring these solutions, we can also learn many classic programming ideas to help us use the framework more reasonably and solve business problems with technology.

Keywords: Front-end React Fragment Vue Programming

Added by Lisa23 on Mon, 04 Nov 2019 03:55:45 +0200