react hooks使用_使用React Hooks将React类组件转换为功能组件的五种方法

news/2024/7/4 10:25:46

react hooks使用

The latest alpha release of React introduced a new concept called Hooks. Hooks were introduced to React to solve common problems; however, they primarily serve as an alternative for classes. With Hooks, you can create functional components that uses state and lifecycle methods.

React的最新alpha版本引入了一个称为Hooks的新概念。 在React中引入了钩子以解决常见问题 ; 但是,它们主要用作类的替代方法。 使用挂钩,您可以创建使用状态和生命周期方法的功能组件。

Hooks are currently available in React v16.7.0-alpha, though there are no plans to remove classes. Hooks just provide another way to write React.

尽管没有计划删除类,但是钩子在React v16.7.0-alpha中当前可用。 钩子只是提供了另一种编写React的方式。

Given that Hooks are still new, many developers are looking to apply the concept in their existing React applications or new applications. In this post, we’ll look at five ways to convert React class components to functional components using React Hooks.

鉴于Hook仍然是新手,因此许多开发人员正在寻求将该概念应用到他们现有的React应用程序或新应用程序中。 在本文中,我们将探讨使用React Hooks将React类组件转换为功能组件的五种方法。

查看没有状态或生命周期方法的类 (Looking at a Class Without State or Lifecycle Methods)

To begin, we will look at a React class that has neither state nor lifecycle components. This class alerts a name when a user clicks a button:

首先,我们将看看既没有状态也没有生命周期组件的React类。 当用户单击按钮时,此类会警告名称:

import React, { Component } from 'react';

class App extends Component {

  alertName = () => {
    alert('John Doe');
  };

  render() {
    return (
      <div>
        <h3> This is a Class Component </h3>
        <button onClick={this.alertName}> Alert </button>
      </div>
    );
  }
}

export default App;

Here we have a typical React class, which lacks state or a lifecycle method. It alerts a name when a button is clicked. The functional equivalent of this class will look like this:

在这里,我们有一个典型的React类,它缺少状态或生命周期方法。 单击按钮时,它会提醒名称。 该类的功能等效项如下所示:

import React from 'react';

function App() {
  const alertName = () => {
    alert(' John Doe ');
  };

  return (
    <div>
      <h3> This is a Functional Component </h3>
      <button onClick={alertName}> Alert </button>
    </div>
  );
};

export default App;

Like the first example, this functional class behaves in a typical way. We haven’t used Hooks or anything new yet. In these examples, we have no need for state or lifecycle.

像第一个示例一样,该功能类的行为也很典型。 我们还没有使用过Hooks或其他任何新东西。 在这些示例中,我们不需要状态或生命周期。

We can change that now and look at situations where we have a class-based component with state and learn how to convert it to a functional component using Hooks.

现在,我们可以更改它,并查看具有状态的基于类的组件的情况,并学习如何使用Hooks将其转换为功能组件。

将钩子添加到带有状态的类中 (Adding Hooks to Classes with State)

Let’s consider a situation where we have a global name variable that we can update within the app from a text input field. In React, we handle cases like this by defining the name variable in a state object and calling setState() when we have a new value to update the name variable with:

让我们考虑一种情况,我们有一个全局名称变量,可以从文本输入字段在应用程序中更新它。 在React中,我们通过在state对象中定义名称变量并在有新值更新name变量时调用setState()处理此类情况:

import React, { Component } from 'react';

class App extends Component {
state = {
      name: ''
  }

  alertName = () => {
    alert(this.state.name);
  };

  handleNameInput = e => {
    this.setState({ name: e.target.value });
  };

  render() {
    return (
      <div>
        <h3> This is a Class Component </h3>
        <input
          type="text"
          onChange={this.handleNameInput}
          value={this.state.name}
          placeholder="Your name"
        />
        <button onClick={this.alertName}> Alert </button>
      </div>
    );
  }
}

export default App;

When a user types a name in the input field and clicks the Alert button, it alerts the name we’ve defined in state.

当用户在输入字段中输入名称并单击“ Alert按钮时,它将警告我们在状态中定义的名称。

We can convert this entire class into a functional React component using Hooks:

我们可以使用Hooks将整个类转换为功能性的React组件:

import React, { useState } from 'react';

function App() {

  const [name, setName] = useState('John Doe');

  const alertName = () => {
    alert(name);
  };

  const handleNameInput = e => {
    setName(e.target.value);
  };

  return (
    <div>
      <h3> This is a Functional Component </h3>
      <input
        type="text"
        onChange={handleNameInput}
        value={name}
        placeholder="Your name"
      />
      <button onClick={alertName}> Alert </button>
    </div>
  );
};

export default App;

Here, we introduced the useState Hook. It allows us to make use of state in React functional components. With the useState() Hook, we can use state in this functional component. It uses a similar syntax with destructuring assignment for arrays. Consider this line :

在这里,我们介绍了useState Hook。 它允许我们在React功能组件中使用状态。 借助useState()挂钩,我们可以在此功能组件中使用状态。 它使用类似的语法对数组进行解构分配。 考虑这一行:

const [name, setName] = useState("John Doe")

Here, name is the equivalent of this.state in a normal class components while setName is the equivalent of this.setState .

在这里, name是相当于this.state在正常类组件,同时setName是相当于this.setState

The initial value of the state in the useState() Hook comes from an argument. In other words, the useState() argument is the initial value of the state. In our case, we set it to "John Doe": this means that the initial state of the name in state is John Doe.

useState()挂钩中的状态的初始值来自一个参数。 换句话说, useState()参数是状态的初始值。 在我们的例子中,我们将其设置为"John Doe" :这意味着状态中名称的初始状态为John Doe。

This code is an example of how you can convert a class-based React component with state to a functional component using Hooks. We can now look at a few more examples, including classes with multiple state properties.

这段代码是一个示例,说明如何使用Hooks将具有状态的基于类的React组件转换为功能组件。 现在,我们可以看更多示例,包括具有多个状态属性的类。

将钩子添加到具有多个状态属性的类 (Adding Hooks to Classes with Multiple State Properties)

We have looked at how you might convert one state property with useState, but the same approach won’t quite work when you have multiple state properties. If, for example, we had two or more input fields for userName, firstName, and lastName, then we would have a class-based component with three state properties:

我们已经研究了如何使用useState转换一个状态属性,但是当您具有多个状态属性时,相同的方法将行不通。 例如,如果我们有两个或多个userNamefirstNamelastName输入字段,那么我们将有一个基于类的组件,具有三个状态属性:

import React, { Component } from 'react';

class App extends Component {

    state = {
      userName: '',
      firstName: '',
      lastName: ''
    };

  logName = () => {
    // do whatever with the names ... let's just log them here
    console.log(this.state.userName);
    console.log(this.state.firstName);
    console.log(this.state.lastName);
  };

  handleUserNameInput = e => {
    this.setState({ userName: e.target.value });
  };
  handleFirstNameInput = e => {
    this.setState({ firstName: e.target.value });
  };
  handleLastNameInput = e => {
    this.setState({ lastName: e.target.value });
  };

  render() {
    return (
      <div>
        <h3> This is a Class Component </h3>
        <input
          type="text"
          onChange={this.handleUserNameInput}
          value={this.state.userName}
          placeholder="Your username"
        />
        <input
          type="text"
          onChange={this.handleFirstNameInput}
          value={this.state.firstName}
          placeholder="Your firstname"
        />
        <input
          type="text"
          onChange={this.handleLastNameInput}
          value={this.state.lastName}
          placeholder="Your lastname"
        />
        <button className="btn btn-large right" onClick={this.logName}>
          {' '}
          Log Names{' '}
        </button>
      </div>
    );
  }
}

export default App;

To convert this class to a functional component with Hooks, we’ll have to take a somewhat unconventional route. Using the useState() Hook, the above example can be written as:

要将此类转换为带有Hooks的功能组件,我们将不得不采取一些非常规的方法。 使用useState()挂钩,以上示例可以写成:

import React, { useState } from 'react';

function App() {

  const [userName, setUsername] = useState('');
  const [firstName, setFirstname] = useState('');
  const [lastName, setLastname] = useState('');

  const logName = () => {
    // do whatever with the names... let's just log them here
    console.log(userName);
    console.log(firstName);
    console.log(lastName);
  };

  const handleUserNameInput = e => {
    setUsername(e.target.value);
  };
  const handleFirstNameInput = e => {
    setFirstname(e.target.value);
  };
  const handleLastNameInput = e => {
    setLastname(e.target.value);
  };

  return (
    <div>
      <h3> This is a functional Component </h3>

      <input
        type="text"
        onChange={handleUserNameInput}
        value={userName}
        placeholder="username..."
      />
      <input
        type="text"
        onChange={handleFirstNameInput}
        value={firstName}
        placeholder="firstname..."
      />
      <input
        type="text"
        onChange={handleLastNameInput}
        value={lastName}
        placeholder="lastname..."
      />
      <button className="btn btn-large right" onClick={logName}>
        {' '}
        Log Names{' '}
      </button>
    </div>
  );
};

export default App;

This demonstrates how we can convert a class-based component with multiple state properties to a functional component using the useState() Hook.

这演示了如何使用useState()挂钩将具有多个状态属性的基于类的组件转换为功能组件。

Here’s a Codesandbox for this example.

这是此示例的Codesandbox 。

使用State和componentDidMount将钩子添加到类中 (Adding Hooks to a Class with State and componentDidMount)

Let’s consider a class with state and componentDidMount. To demonstrate, we will look at a scenario where we set an initial state for the three input fields and have them all update to a different set of values after five seconds.

让我们考虑一个带有statecomponentDidMount的类。 为了演示,我们将看一个场景,其中我们为三个输入字段设置了初始状态,并在五秒钟后将它们全部更新为一组不同的值。

To achieve this, we will declare an initial state value for the input fields and implement a componentDidMount() lifecycle method that will run after the initial render to update the state values:

为此,我们将为输入字段声明一个初始状态值,并实现一个componentDidMount()生命周期方法,该方法将在初始渲染后运行以更新状态值:

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

class App extends Component {
    state = {
      // initial state
      userName: 'JD',
      firstName: 'John',
      lastName: 'Doe'
  }

  componentDidMount() {
    setInterval(() => {
      this.setState({
        // update state
        userName: 'MJ',
        firstName: 'Mary',
        lastName: 'jane'
      });
    }, 5000);
  }

  logName = () => {
    // do whatever with the names ... let's just log them here
    console.log(this.state.userName);
    console.log(this.state.firstName);
    console.log(this.state.lastName);
  };

  handleUserNameInput = e => {
    this.setState({ userName: e.target.value });
  };
  handleFirstNameInput = e => {
    this.setState({ firstName: e.target.value });
  };
  handleLastNameInput = e => {
    this.setState({ lastName: e.target.value });
  };

  render() {
    return (
      <div>
        <h3> The text fields will update in 5 seconds </h3>
        <input
          type="text"
          onChange={this.handleUserNameInput}
          value={this.state.userName}
          placeholder="Your username"
        />
        <input
          type="text"
          onChange={this.handleFirstNameInput}
          value={this.state.firstName}
          placeholder="Your firstname"
        />
        <input
          type="text"
          onChange={this.handleLastNameInput}
          value={this.state.lastName}
          placeholder="Your lastname"
        />
        <button className="btn btn-large right" onClick={this.logName}>
          {' '}
          Log Names{' '}
        </button>
      </div>
    );
  }
}

export default App;

When the app runs, the input fields will have the initial values we’ve defined in the state object. These values will then update to the values we’ve defined inside the componentDidMount() method after five seconds.

当应用运行时,输入字段将具有我们在状态对象中定义的初始值。 五秒钟后,这些值将更新为我们在componentDidMount()方法内定义的值。

Next, we will convert this class to a functional component using the React useState and useEffect Hooks:

接下来,我们将使用React useStateuseEffect Hooks将此类转换为功能组件:

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

function App() {

  const [userName, setUsername] = useState('JD');
  const [firstName, setFirstname] = useState('John');
  const [lastName, setLastname] = useState('Doe');

  useEffect(() => {
    setInterval(() => {
      setUsername('MJ');
      setFirstname('Mary');
      setLastname('Jane');
    }, 5000);
  });

  const logName = () => {
    // do whatever with the names ...
    console.log(this.state.userName);
    console.log(this.state.firstName);
    console.log(this.state.lastName);
  };

  const handleUserNameInput = e => {
    setUsername({ userName: e.target.value });
  };
  const handleFirstNameInput = e => {
    setFirstname({ firstName: e.target.value });
  };
  const handleLastNameInput = e => {
    setLastname({ lastName: e.target.value });
  };

  return (
    <div>
      <h3> The text fields will update in 5 seconds </h3>
      <input
        type="text"
        onChange={handleUserNameInput}
        value={userName}
        placeholder="Your username"
      />
      <input
        type="text"
        onChange={handleFirstNameInput}
        value={firstName}
        placeholder="Your firstname"
      />
      <input
        type="text"
        onChange={handleLastNameInput}
        value={lastName}
        placeholder="Your lastname"
      />
      <button className="btn btn-large right" onClick={logName}>
        {' '}
        Log Names{' '}
      </button>
    </div>
  );
};

export default App;

In terms of functionality, this component does exactly the same thing as the previous example. The only difference is that instead of using the conventional state object and componentDidMount() lifecycle method as we did in the class component, we used the useState and useEffect Hooks. Here’s a Codesanbox for this example.

在功能方面,此组件的作用与上一个示例完全相同。 唯一的区别是,我们没有使用在类组件中使用的常规state对象和componentDidMount()生命周期方法,而是使用了useStateuseEffect Hooks。 这是此示例的Codesanbox 。

使用State, componentDidMountcomponentDidUpdate将钩子添加到类中 (Adding Hooks to a Class with State, componentDidMount, and componentDidUpdate)

Next, let’s look at a React class with state and two lifecycle methods: componentDidMount and componentDidUpdate. So far, you may have noticed that we’ve mostly been working with the useState Hook. In this example, we will focus on the useEffect Hook.

接下来,让我们看一下带有状态和两个生命周期方法的React类: componentDidMountcomponentDidUpdate 。 到目前为止,您可能已经注意到我们一直在使用useState Hook。 在此示例中,我们将重点介绍useEffect Hook。

To best demonstrate how this works, let’s update our code to dynamically update the <h3> header on the page. Currently the header says This is a Class Component. Now we’ll define a componentDidMount() method to update the header to say Welcome to React Hooks after three seconds:

为了最好地演示它是如何工作的,让我们更新代码以动态更新页面上的<h3>标头。 当前标题显示“ This is a Class Component 。 现在,我们将定义一个componentDidMount()方法,以在三秒钟后更新标头以显示“ Welcome to React Hooks

import React, { Component } from 'react';

class App extends Component {
state = {
      header: 'Welcome to React Hooks'

  }

  componentDidMount() {
    const header = document.querySelectorAll('#header')[0];
    setTimeout(() => {
      header.innerHTML = this.state.header;
    }, 3000);
  }

  logName = () => {
    // do whatever with the names ...
  };

  // { ... }

  render() {
    return (
      <div>
        <h3 id="header"> This is a Class Component </h3>
        <input
          type="text"
          onChange={this.handleUserNameInput}
          value={this.state.userName}
          placeholder="Your username"
        />
        <input
          type="text"
          onChange={this.handleFirstNameInput}
          value={this.state.firstName}
          placeholder="Your firstname"
        />
        <input
          type="text"
          onChange={this.handleLastNameInput}
          value={this.state.lastName}
          placeholder="Your lastname"
        />
        <button className="btn btn-large right" onClick={this.logName}>
          {' '}
          Log Names{' '}
        </button>
      </div>
    );
  }
}

export default App;

When the app runs, it will start with the initial header This is a Class Component and change it to Welcome to React Hooks after three seconds. This is the classic componentDidMount() behavior since it runs after the render function is executed successfully.

当应用运行时,它将以初始标头“ This is a Class Component并在三秒钟后将其更改为“ Welcome to React Hooks 。 这是经典的componentDidMount()行为,因为它在成功执行render函数之后运行。

What if we want to dynamically update the header from another input field, so that the header gets updated with the new text while we type? To do that, we’ll need to implement the componentDidUpdate() lifecycle method like this:

如果我们想从另一个输入字段动态更新标题,以便在键入时使用新文本更新标题,该怎么办? 为此,我们需要实现这样的componentDidUpdate()生命周期方法:

import React, { Component } from 'react';

class App extends Component {
  state = {
      header: 'Welcome to React Hooks'
  }

  componentDidMount() {
    const header = document.querySelectorAll('#header')[0];
    setTimeout(() => {
      header.innerHTML = this.state.header;
    }, 3000);
  }

  componentDidUpdate() {
    const node = document.querySelectorAll('#header')[0];
    node.innerHTML = this.state.header;
  }

  logName = () => {
    // do whatever with the names ... let's just log them here
    console.log(this.state.username);
  };

  // { ... }

  handleHeaderInput = e => {
    this.setState({ header: e.target.value });
  };

  render() {
    return (
      <div>
        <h3 id="header"> This is a Class Component </h3>
        <input
          type="text"
          onChange={this.handleUserNameInput}
          value={this.state.userName}
          placeholder="Your username"
        />
        <input
          type="text"
          onChange={this.handleFirstNameInput}
          value={this.state.firstName}
          placeholder="Your firstname"
        />
        <input
          type="text"
          onChange={this.handleLastNameInput}
          value={this.state.lastName}
          placeholder="Your lastname"
        />
        <button className="btn btn-large right" onClick={this.logName}>
          {' '}
          Log Names{' '}
        </button>
        <input
          type="text"
          onChange={this.handleHeaderInput}
          value={this.state.header}
        />{' '}
      </div>
    );
  }
}

export default App;

Here, we have state, componentDidMount() and componentDidUpdate() . So far, when you run the app, the header will update to Welcome to React Hooks after three seconds, thanks to our componentDidMount() function. When you start typing in the header text input field, the <h3> text will update with the input text as defined in the componentDidUpdate() method.

在这里,我们有statecomponentDidMount()componentDidUpdate() 。 到目前为止,由于我们的componentDidMount()函数,运行应用程序时,标头将在三秒钟后更新为Welcome to React Hooks 。 当您开始在标题文本输入字段中输入内容时, <h3>文本将使用componentDidUpdate()方法中定义的输入文本进行更新。

Next, we will convert this class to a functional component with the useEffect() Hook:

接下来,我们将使用useEffect()挂钩将此类转换为功能组件:

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

function App() {

  const [userName, setUsername] = useState('');
  const [firstName, setFirstname] = useState('');
  const [lastName, setLastname] = useState('');
  const [header, setHeader] = useState('Welcome to React Hooks');

  const logName = () => {
    // do whatever with the names...
    console.log(userName);
  };

  useEffect(() => {
    const newheader = document.querySelectorAll('#header')[0];
    setTimeout(() => {
      newheader.innerHTML = header;
    }, 3000);
  });

  const handleUserNameInput = e => {
    setUsername(e.target.value);
  };
  const handleFirstNameInput = e => {
    setFirstname(e.target.value);
  };
  const handleLastNameInput = e => {
    setLastname(e.target.value);
  };
  const handleHeaderInput = e => {
    setHeader(e.target.value);
  };

  return (
    <div>
      <h3 id="header"> This is a functional Component </h3>

      <input
        type="text"
        onChange={handleUserNameInput}
        value={userName}
        placeholder="username..."
      />
      <input
        type="text"
        onChange={handleFirstNameInput}
        value={firstName}
        placeholder="firstname..."
      />
      <input
        type="text"
        onChange={handleLastNameInput}
        value={lastName}
        placeholder="lastname..."
      />
      <button className="btn btn-large right" onClick={logName}>
        {' '}
        Log Names{' '}
      </button>
      <input type="text" onChange={handleHeaderInput} value={header} />
    </div>
  );
};

export default App;

We achieved the same functionality with this component as we did with the previous using the useEffect() Hook. We optimized the code as well, since we didn’t have to write separate code for the componentDidMount() and componentDidUpdate() functions. With the useEffect() Hook, we get the functionality of both. This is because useEffect() runs both after the initial render and after every subsequent update by default.

通过使用useEffect()挂钩,该组件实现了与先前组件相同的功能。 我们也优化了代码,因为我们不必为componentDidMount()componentDidUpdate()函数编写单独的代码。 使用useEffect()挂钩,我们可以同时获得两者的功能。 这是因为useEffect()在默认情况下在初始渲染之后和每个后续更新之后都运行。

Check out this example on this CodeSandbox.

在此CodeSandbox上查看此示例。

将PureComponent转换为React备忘录 (Converting PureComponent to React memo)

React PureComponent works in a similar manner to Component. The major difference between them is that React.Component doesn’t implement the shouldComponentUpdate() lifecycle method while React.PureComponent does. If you have an application where the render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases.

React PureComponent的工作方式与Component相似。 它们之间的主要区别在于, React.Component并未实现shouldComponentUpdate()生命周期方法,而React.PureComponent却实现了该方法。 如果您有一个应用程序,其中render()函数在给定相同的道具和状态的情况下呈现相同的结果,则可以在某些情况下使用React.PureComponent来提高性能。

Related Reading: React 16.6: React.memo() for Functional Components Rendering Control

相关阅读: React 16.6:React.memo()用于功能组件的渲染控制

React.memo() works in a similar way. When your function component renders the same result given the same props, you can wrap it in a call to React.memo() to enhance performance. Using PureComponent and React.memo() gives React applications a considerable increase in performance as it reduces the number of render operations in the app.

React.memo()以类似的方式工作。 当您的功能组件使用相同的道具呈现相同的结果时,可以将其包装在对React.memo()的调用中以提高性能。 使用PureComponentReact.memo()使React应用程序的性能大大提高,因为它减少了应用程序中的渲染操作数量。

Here, we’ll demonstrate how to convert a PureComponent class to a React memo component. To understand what they both do, we will first look at code where a component renders every two seconds, whether or not there’s a change in value or state:

在这里,我们将演示如何将PureComponent类转换为React备忘录组件。 为了了解它们的作用,我们将首先查看组件每两秒钟渲染一次的代码,无论值或状态是否发生变化:

import React, { Component } from 'react';

function Unstable(props) {
  // monitor how many times this component is rendered
  console.log(' Rendered this component ');
  return (
    <div>
      <p> {props.value}</p>
    </div>
  );
};

class App extends Component {
  state = {
    value: 1
  };

  componentDidMount() {
    setInterval(() => {
      this.setState(() => {
        return { value: 1 };
      });
    }, 2000);
  }

  render() {
    return (
      <div>
        <Unstable value={this.state.value} />
      </div>
    );
  }
}
export default App;

When you run the app and check the logs, you’ll notice that it renders the component every two seconds, without any change in state or props. This is a situation that we can improve with both PureComponent and React.memo().

当您运行该应用程序并检查日志时,您会注意到它每两秒钟渲染一次组件,而状态或道具没有任何变化。 我们可以使用PureComponentReact.memo()改善这种情况。

Most of the time, we only want to re-render a component when there’s been a change in state or props. Using the example above, we can improve it with PureComponent so that the component only re-renders when there’s a change in state or props. We do this by importing PureComponent and extending it like this:

大多数时候,我们只想在状态或道具发生变化时重新渲染组件。 使用上面的示例,我们可以使用PureComponent对其进行改进,以使该组件仅在状态或道具发生变化时才重新渲染。 我们通过导入PureComponent并像这样扩展它来做到这一点:

import React, { PureComponent } from 'react';

function Unstable(props) {
  console.log(' Rendered Unstable component ');
  return (
    <div>
      <p> {props.value}</p>
    </div>
  );
};

class App extends PureComponent {
  state = {
    value: 1
  };

  componentDidMount() {
    setInterval(() => {
      this.setState(() => {
        return { value: 1 };
      });
    }, 2000);
  }

  render() {
    return (
      <div>
        <Unstable value={this.state.value} />
      </div>
    );
  }
}
export default App;

Now if you run the app again, you only get the initial render. Nothing else happens after that. This is because we have class App extends PureComponent{} instead of class App extends Component{}.

现在,如果再次运行该应用程序,则只会获得初始渲染。 在那之后没有其他事情发生。 这是因为我们有class App extends PureComponent{} class App extends Component{}而不是class App extends Component{}

This solves the problem of components being re-rendered without respect to the current state. However, if we implement a state change within our setState method, we would run into another issue. For example, consider the following changes to setState():

这解决了不考虑当前状态而重新渲染组件的问题。 但是,如果我们在setState方法中实现状态更改,则会遇到另一个问题。 例如,考虑对setState()的以下更改:

componentDidMount() {
    setInterval(() => {
      this.setState(() => {
        return { value: 1 };
      });
    }, 2000);
  }
componentDidMount() {
    setInterval(() => {
      this.setState(() => {
        return { value: Math.random() };
      });
    }, 2000);
  }

The component will re-render each time the value updates to the next random number, since, as we have discussed, PureComponent makes it possible to re-render components only when there’s been a change in state or props.

每次值更新为下一个随机数时,组件都会重新渲染,因为正如我们已经讨论的那样, PureComponent使得仅当状态或道具发生变化时才可以重新渲染组件。

Now we can look at how to use React.memo() to achieve the same fix. To do this with React memo, wrap the component with React.memo():

现在我们可以看看如何使用React.memo()来实现相同的修复。 要使用React备忘录做到这一点,请使用React.memo()包装组件:

import React, { Component } from "react";

const Unstable = React.memo(function Unstable (props) {
  console.log(" Rendered Unstable component ");
  return <div>{props.val} </div>;
});

class App extends Component {
  state = {
    val: 1
  };

  componentDidMount() {
    setInterval(() => {
      this.setState({ val: 1 });
    }, 2000);
  }

  render() {
    return (
      <div>
        <header className="App-header">
          <Unstable val={this.state.val} />
        </header>
      </div>
    );
  }
}

export default App;

This achieves the same result as using PureComponent. Hence, the component only renders after the initial render and doesn’t re-render again until there’s a change in state or props. Here’s the Codesandbox for this example.

这样可以获得与使用PureComponent相同的结果。 因此,该组件仅在初始渲染之后渲染,并且直到状态或道具发生变化时才再次重新渲染。 这是此示例的Codesandbox 。

结论 (Conclusion)

In this post we have gone through a few ways you can covert an existing class-based component to a functional component using React Hooks. We have also looked at a special case of converting a React PureComponent class to React.memo().

在本文中,我们介绍了几种使用React Hooks将现有的基于类的组件转换为功能组件的方法。 我们还研究了将React PureComponent类转换为React.memo()的特殊情况。

To use Hooks in your applications, be sure to update your version of React to the supported version:

要在您的应用程序中使用Hooks,请确保将您的React版本更新为支持的版本:

"react": "^16.7.0-alpha",
    "react-dom": "^16.7.0-alpha",

You now have a foundation to experiment further with React Hooks.

现在,您已经有了一个基础,可以进一步使用React Hooks进行实验。

Related Reading:

相关阅读:

  • Getting Started with React Hooks

    React Hooks入门

  • Build a React To-Do App with React Hooks (No Class Components)

    使用React Hooks构建一个React To-Do应用(无类组件)

翻译自: https://www.digitalocean.com/community/tutorials/five-ways-to-convert-react-class-components-to-functional-components-with-react-hooks

react hooks使用


http://www.niftyadmin.cn/n/3649143.html

相关文章

Genymotion安卓模拟器常见问题汇总

Genymotion模拟器在安装好多由于电脑设备的关系可能出现兼容性、网络连接等问题&#xff0c;这里带来它们的解决方法。 1、关于兼容性的关键 下载完把这个zip文件&#xff08;点我下载&#xff09;直接拖到手机虚拟屏幕上就会提示安装&#xff0c;安装完了就会要求重启手机&…

Ubuntu 12.04下LAMP安装配置(转)

想要安装一台 Ubuntu 12.04版的Linux服务器&#xff0c;用这台服务器上的LAMP套件来运行我自己的个人网站。LAMP套件就是“LinuxApacheMysqlPHP这四款软件组成了一个可以使网站运行的套装工具软件。”通过安装尝试&#xff0c;我获得了一些成功的安装配置经验&#xff0c;通过本…

Retrofit的简单使用

一、Retorfit简介 Retorfit是一个功能强大的联网工具。可以看成是OKHttp数据解析&#xff08;json、xml等&#xff09;的组合。 说明文档&#xff1a;http://square.github.io/retrofit/ GitHub:https://github.com/square/retrofit 二、使用手册 1.引入配置 添加Retrofit依赖:…

如何为自定义Vue.js组件添加`v-model`支持

介绍 (Introduction) The v-model directive is one of the few directives that comes bundled with Vue.js. This directive allows for two-way data binding between our data and views. v-model指令是Vue.js附带的少数几个指令之一。 该指令允许在我们的数据和视图之间进…

mongodb启动失败[转]

现象&#xff1a; 查看日志的内容如下 Tue Jan 4 09:51:37 MongoDB starting : pid2794 port27017 dbpath/var/lib/mongodb 32-bit ** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data ** see http://blog.mongodb.org/post/137788967/…

Android的各种Drawable讲解

Android把可绘制的对象抽象为Drawable&#xff0c;不同的图形图像资源就代表着不同的drawable类型。Android FrameWork提供了一些具体的Drawable实现&#xff0c;通常在代码中都不会直接接触Drawable的实现类。在实际的开发过程中&#xff0c;会把使用到的资源都放置在res/draw…

使用黑盒测试在 Go 中重写 Bash 脚本

目录 前言&#xff1a; 开始 准备工作 描述行为&#xff1a;Bats 简介 行为描述&#xff1a;陷阱 描述行为&#xff1a;设计测试 重写&#xff1a;让我们开始用go吧&#xff01; 重构和更新&#xff1a;实现胜利 结论 前言&#xff1a; 使用黑盒测试在Go中重写Bash脚本…

Ormlite的工具使用

配置 compile com.j256.ormlite:ormlite-android:5.0 使用 常用注解 DatabaseTable(tableName "t_user") 指定实体和表的一一对应关系 DatabaseField() 指定属性与表中列的一一对应关系 常用配置说明&#xff1a; 主键&#xff1a;id true 自增主键&#xff1a;gen…