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

react hooks使用

In the latest alpha release of React, a new concept was introduced, it is called Hooks. Hooks were introduced to React to solve many problems as explained in the introduction to Hooks session however, it primarily serves as an alternative for classes. With Hooks, we can create functional components that uses state and lifecycle methods.

在最新的React alpha版本中,引入了一个新概念,称为Hooks。 正如Hooks会话简介中所介绍的那样,将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应用(无类组件)

Hooks are relatively new, as matter of fact, it is still a feature proposal. However, it is available for use at the moment if you'd like to play with it and have a closer look at what it offers. Hooks are currently available in React v16.7.0-alpha.

挂钩是相对较新的,事实上,它仍然是一项功能建议。 但是,如果您想使用它并仔细查看它提供的功能,则可以使用它。 钩子目前在React v16.7.0-alpha中可用。

It's important to note that there are no plans to ditch classes. React Hooks just give us another way to write React. And that's a good thing!

重要的是要注意,没有放弃课程的计划。 React Hooks 只是给了我们另一种编写React的方式 。 那是一件好事!

Given that Hooks are still new, many developers are yet to grasp its concepts or understand how to apply it in their existing React applications or even in creating new React apps. In this post, we'll demonstrate 5 simple way to convert React Class Components to Functional Components using React Hooks.

鉴于Hook仍然是新手,许多开发人员尚未掌握其概念或了解如何将其应用到现有的React应用程序中,甚至无法创建新的React应用程序。 在本文中,我们将演示5种使用React Hooks将React类组件转换为功能组件的简单方法。

没有状态或生命周期方法的类 ( Class without state or lifecycle methods )

Let's start off with a simple React class that has neither state nor lifecycle components. Lets use a class that simply 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 usual React class, nothing new and nothing unusual. This class doesn't have state or any lifecycle method in it. It just 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 class component we had earlier, there's nothing new or unusual here. We haven't even used Hooks or anything new as of yet. This is because we've only considered an example where we have no need for state or lifecycle. But let's change that now and look at situations where we have a class based component with state and see how to convert it to a functional component using Hooks.

就像我们之前的类组件一样,这里没有新的或不寻常的。 到目前为止,我们甚至都没有使用过Hooks或任何新东西。 这是因为我们仅考虑了一个不需要状态或生命周期的示例。 但是,现在让我们进行更改,看看有一个带有状态的基于类的组件,并了解如何使用Hooks将其转换为功能组件。

状态类 ( Class 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 click the Alert button, it alerts the name we've defined in state. Once again this is a simple React concept, however, we can convert this entire class into a functional React component using Hooks like this:

当用户在输入字段中输入名称并单击“ Alert按钮时,它将警报我们在状态中定义的名称。 再次,这是一个简单的React概念,但是,我们可以使用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 serves as a way of making use of state in React functional components. With theuseState() Hook, we've been able to 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 . The last thing to understand while using the useState() Hook is that it takes an argument that serves as the initial value of the state. Simply put, the useState() argument is the initial value of the state. In our case, we set it to "John Doe" such that the initial state of the name in state is John Doe.

在这里, name是相当于this.state在正常类组件,同时setName是相当于this.setState 。 使用useState()挂钩时要了解的最后一件事是,它接受一个用作状态初始值的参数。 简而言之, useState()参数是状态的初始值。 在本例中,我们将其设置为"John Doe" ,以使处于状态的名称的初始状态为John Doe。

This is primarily how to convert a class based React component with state to a functional component using Hooks. There are a lot more other useful ways of doing this as we'll see in subsequent examples.

这主要是如何使用Hooks将具有状态的基于类的React组件转换为功能组件。 如后面的示例所示,还有许多其他有用的方法可以做到这一点。

具有多个状态属性的类 ( Class with multiple state properties )

It is one thing to easily convert one state property with useState however, the same approach doesn't quite apply when you have to deal with multiple state properties. Take for instance we had two or more input fields for userName, firstName and lastName then we would have a class based component with three state properties like this:

轻松地使用useState转换一个状态属性是useState但是,当您必须处理多个状态属性时,该方法并不适用。 例如,对于userName, firstName and lastName我们有两个或多个输入字段userName, firstName and lastName那么我们将有一个基于类的组件,具有三个状态属性,如下所示:

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 the Codesandbox for this example.

这是此示例的Codesandbox 。

具有状态和componentDidMount的类 ( Class with state and componentDidMount )

Let's consider a class with only state and componentDidMount. To demonstrate such a class, let's create 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 5 seconds.

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

To achieve this, we'll have to 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 intial values we've defined in the state object. These values will then update to the values we've define inside the componentDidMount() method after 5 seconds. Now, let's convert this class to a functional component using the React useState and useEffect Hooks.

当应用运行时,输入字段将具有我们在状态对象中定义的初始值。 5秒钟后,这些值将更新为我们在componentDidMount()方法内定义的值。 现在,让我们使用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 ;

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

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

具有状态,componentDidMount和componentDidUpdate的类 ( Class with state, componentDidMount and componentDidUpdate )

Next, let's look at a React class with state and two lifecycle methods. So far you may have noticed that we've mostly been working with the useState Hook. In this example, let's pay more attention to the useEffect Hook.

接下来,让我们看一下带有状态和两个生命周期方法的React类。 到目前为止,您可能已经注意到我们大部分时候都在使用useState Hook。 在此示例中,让我们更加关注useEffect Hook。

To best demonstrate how this works, let's update our code to dynamically update the

header of 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 3 seconds:

为了最好地演示它是如何工作的,让我们更新代码以动态更新页面的

标头。 当前标题显示“ 这是一个类组件” 。 现在,我们将定义一个componentDidMount()方法,以在3秒后更新标头以显示“ 欢迎使用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;

At this point, when the app runs, it starts with the initial header This is a Class Component and changes to Welcome to React Hooks after 3 seconds. This is the classic componentDidMount() behaviour since it runs after the render function is executed successfully.

此时,当应用程序运行时,它从初始标头“ This is a Class Component”开始,并在3秒钟后变为“ 欢迎使用React Hooks” 。 这是经典的componentDidMount()行为,因为它在成功执行render函数之后运行。

What if we want to dynamically update the header from another input field such that while we type, the header gets updated with the new text. To do that, we'll need to also 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 updates to Welcome to React Hooks after 3 seconds as we defined in componentDidMount(). Then when you start typing in the header text input field, the

text will update with the input text as defined in the componentDidUpdate() method. Now lets convert this class to a functional component with the useEffect() Hook.

在这里,我们有statecomponentDidMount()componentDidUpdate() 。 到目前为止,当您运行应用程序时,标头将在3秒钟后更新为Welcome to React Hooks ,如我们在componentDidMount()定义的那样。 然后,当您开始输入标题文本输入字段时,

文本将使用componentDidUpdate()方法中定义的输入文本进行更新。 现在,使用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've achieved exactly the same functionailty using the useEffect() Hook. It's even better or cleaner as some would say because here, we didn't have to write separate codes for componentDidMount() and componentDidUpdate(). With the useEffect() Hook, we are able to achieve both functions. This is because by default, useEffect() runs both after the initial render and after every subsequent update. Check out this example on this CodeSandbox.

我们使用useEffect() Hook实现了完全相同的功能。 就像有些人说的那样,它更好或更干净,因为在这里,我们不必为componentDidMount()componentDidUpdate()编写单独的代码。 使用useEffect()挂钩,我们能够实现这两个功能。 这是因为默认情况下, useEffect()在初始渲染之后和每个后续更新之后都运行。 在此CodeSandbox上查看此示例。

将PureComponent转换为React备忘录 ( Convert 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 implements it. If your application's 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实现shouldComponentUpdate()生命周期方法。 如果应用程序的render()函数在相同的道具和状态下呈现相同的结果,则在某些情况下可以使用React.PureComponent来提高性能。

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

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

The same thing applies to React.memo(). While the former refers to class based componentrs, React memo refers to functional components such that 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备忘录指的是功能组件,以便当您的功能组件在给定相同的道具时呈现相同的结果时,您可以将其包装在对React.memo()的调用中以提高性能。 使用PureComponentReact.memo()使React应用程序的性能大大提高,因为它减少了应用程序中的渲染操作数量。

Here, we'll demonstrate how to convert a PureComponent class to a React memo component. To understand what exactly they both do, first, let's simulate a terrible situation where a component renders every 2 seconds wether or not there's a change in value or state. We can quickly create this scenario like this:

在这里,我们将演示如何将PureComponent类转换为React备忘录组件。 为了了解它们的确切作用,首先,让我们模拟一个糟糕的情况,即组件每隔2秒渲染一次,无论其值或状态是否发生变化。 我们可以像这样快速创建这种情况:

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 2 seconds without any change in state or props. As terrible as it is, this is exactly the scenario we wanted to create so we can show you how to fix it with both PureComponent and React.memo().

当您运行该应用程序并检查日志时,您会注意到它每2秒渲染一次组件,而状态或道具没有任何变化。 确实如此,这正是我们想要创建的场景,因此我们可以向您展示如何使用PureComponentReact.memo()对其进行修复。

react hooks使用_使用React Hooks将React类组件转换为功能组件的5种方法_第1张图片

Most of the time, we only want to re-render a component when there's been a change in state or props. Now that we have experienced this awful situation, let's fix it with PureComponent such 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, why's that ? well, instead of class App extends Component{} now we have class App extends PureComponent{}

现在,如果再次运行该应用程序,则只会获得初始渲染。 在那之后什么都没有发生,那是为什么呢? 好吧,现在我们有了class App extends PureComponent{} ,而不是class App extends Component{} class App extends PureComponent{}

react hooks使用_使用React Hooks将React类组件转换为功能组件的5种方法_第2张图片

This solves our problem of re-rendering components, without respect to the current state. If however, we change this method:

这解决了我们不考虑当前状态而重新渲染组件的问题。 但是,如果我们更改此方法:

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

To:

至:

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

The component will re-render each time the value updates to the next random number. So, PureComponent makes it possible to only re-render components when there's been a change in state or props. Now let's see how we can use React.memo() to achieve the same fix. To do this with React memo, simply wrap the component with React.memo() Like this:

每次值更新为下一个随机数时,组件都会重新渲染。 因此, PureComponent使得仅在状态或道具发生更改时才可以重新渲染组件。 现在,让我们看看如何使用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 PureComponent did. 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 demonstrated a few ways to 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(). It may be obvious but i still feel the need to mention that in order to use Hooks in your applications, you'll need to update your React to the supported version:

在本文中,我们演示了几种使用React Hooks将现有的基于类的组件转换为功能组件的方法。 我们还研究了将React PureComponent类转换为React.memo()的特殊情况。 显而易见,但是我仍然需要提及,要在应用程序中使用Hooks,您需要将React更新到支持的版本:

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

React Hooks is still a feature proposal, however, we are hoping that it will be part of the next stable release as it makes it possible for us to eat our cake (use state in function components) and still have it back (retain the simplicity of writing functional components).

React Hooks仍然是一个功能建议,但是,我们希望它会成为下一个稳定版本的一部分,因为它使我们可以吃掉蛋糕(在功能组件中使用状态)并保留它(保持简单性)编写功能组件)。

翻译自: https://scotch.io/tutorials/5-ways-to-convert-react-class-components-to-functional-components-w-react-hooks

react hooks使用

你可能感兴趣的:(java,python,react,javascript,vue)