React 中的 useState() 是什么?

What is useState() in React?

我目前正在学习 React 中的 hooks 概念并试图理解下面的示例。

import { useState } from 'react';

function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

上面的例子增加了处理函数参数本身的计数器。如果我想修改事件处理函数中的计数值怎么办

考虑下面的例子:

setCount = () => {
  //how can I modify count value here. Not sure if I can use setState to modify its value
  //also I want to modify other state values as well here. How can I do that
}

<button onClick={() => setCount()}>
  Click me
</button>

Hooks 是 React v16.7.0-alpha 中的一个新特性 useState 是“Hook”。 useState() 设置任意变量的默认值并在函数组件(PureComponent 函数)中管理。 ex : const [count, setCount] = useState(0); 设置计数 0 的默认值。您可以使用 setCountincrementdecrement 的值。 onClick={() => setCount(count + 1)} 递增计数值。DOC

useState 钩子的语法很简单。

const [value, setValue] = useState(defaultValue)

如果您不熟悉此语法,请转到 here

我建议您阅读 documentation。有很好的解释和大量的例子。

import { useState } from 'react';

function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);
  
  // its up to you how you do it
  const buttonClickHandler = e => {
   // increment
   // setCount(count + 1)
   
   // decrement
   // setCount(count -1)
   
   // anything
   // setCount(0)
  }
  

  return (
       <div>
          <p>You clicked {count} times</p>
         <button onClick={buttonClickHandler}>
             Click me
         </button>
      </div>
   );
 }

React hooks 是一种新的方式(仍在开发中)来访问反应的核心功能,例如 state 而不必使用 classes,在你的例子中如果你想要直接在处理函数中增加一个计数器而不直接在 onClick 属性中指定它,你可以这样做:

...
const [count, setCounter] = useState(0);
const [moreStuff, setMoreStuff] = useState(...);
...

const setCount = () => {
    setCounter(count + 1);
    setMoreStuff(...);
    ...
};

和点击:

<button onClick={setCount}>
    Click me
</button>

让我们快速解释一下这一行是怎么回事:

const [count, setCounter] = useState(0);

useState(0) returns 一个元组,其中第一个参数 count 是计数器的当前状态,setCounter 是允许我们更新计数器状态的方法状态。我们可以使用 setCounter 方法在任何地方更新 count 的状态——在这种情况下,我们在 setCount 函数内部使用它,在那里我们可以做更多的事情;钩子的想法是我们能够让我们的代码更实用,避免基于 class 的组件 if not desired/needed.

I wrote a complete article about hooks with multiple examples (including counters) such as this codepen, I made use of useState, useEffect, useContext, and custom hooks. I could get into more details about how hooks work on this answer but the documentation does a very good job explaining the state hook 和其他钩子的详细信息,希望对您有所帮助。

更新: Hooks are not longer a proposal, since version 16.8 they're now available to be used, there is a section in React's site that answers some of the FAQ.

useState 是 React v16.8.0 中可用的钩子之一。它基本上可以让您将其他 non-stateful/functional 组件转换为可以拥有自己状态的组件。

在最基本的层面上,它是这样使用的:

const [isLoading, setLoading] = useState(true);

这样您就可以调用 setLoading 并传递一个布尔值。 这是拥有 "stateful" 功能组件的一种很酷的方式。

useState() 是一个内置 React 钩子示例,可让您在功能组件中使用状态。在 React 16.7 之前这是不可能的。

useState 函数是一个内置的钩子,可以从 react 包中导入。它允许您向功能组件添加状态。在函数组件中使用 useState 钩子,您可以在不切换到 class 个组件的情况下创建一个状态。

useState0.16.7 版本中可用的内置反应挂钩之一。

useState 应该只在功能组件内部使用。 useState 如果我们需要内部状态并且不需要实现更复杂的逻辑(例如生命周期方法),那么就是这种方式。

const [state, setState] = useState(initialState);

Returns a stateful value, and a function to update it.

During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState).

The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.

请注意 useState 用于更新状态的挂钩回调 与组件 this.setState 的行为不同。为了告诉你区别,我准备了两个例子。

class UserInfoClass extends React.Component {
  state = { firstName: 'John', lastName: 'Doe' };
  
  render() {
    return <div>
      <p>userInfo: {JSON.stringify(this.state)}</p>
      <button onClick={() => this.setState({ 
        firstName: 'Jason'
      })}>Update name to Jason</button>
    </div>;
  }
}

// Please note that new object is created when setUserInfo callback is used
function UserInfoFunction() {
  const [userInfo, setUserInfo] = React.useState({ 
    firstName: 'John', lastName: 'Doe',
  });

  return (
    <div>
      <p>userInfo: {JSON.stringify(userInfo)}</p>
      <button onClick={() => setUserInfo({ firstName: 'Jason' })}>Update name to Jason</button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <UserInfoClass />
    <UserInfoFunction />
  </div>
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

使用 setUserInfo 回调时会创建新对象。请注意,我们丢失了 lastName 键值。为了修复我们可以在 useState.

中传递函数的问题
setUserInfo(prevState => ({ ...prevState, firstName: 'Jason' })

参见示例:

// Please note that new object is created when setUserInfo callback is used
function UserInfoFunction() {
  const [userInfo, setUserInfo] = React.useState({ 
    firstName: 'John', lastName: 'Doe',
  });

  return (
    <div>
      <p>userInfo: {JSON.stringify(userInfo)}</p>
      <button onClick={() => setUserInfo(prevState => ({
        ...prevState, firstName: 'Jason' }))}>
        Update name to Jason
      </button>
    </div>
  );
}

ReactDOM.render(
    <UserInfoFunction />
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

Unlike the setState method found in class components, useState does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax:

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

有关 useState 的更多信息,请参阅 official documentation

useState() 是一个 React 钩子。挂钩使得在函数组件中使用状态和可变性成为可能。

虽然您不能在 classes 中使用挂钩,但您可以使用函数 1 包装 class 组件并使用它的挂钩。这是将组件从 class 迁移到函数形式的好工具。这是一个完整的例子:

对于这个例子,我将使用一个计数器组件。就是这样:

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: props.count };
  }
  
  inc() {
    this.setState(prev => ({count: prev.count+1}));
  }
  
  render() {
    return <button onClick={() => this.inc()}>{this.state.count}</button>
  }
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

它是一个简单的class组件,带有计数状态,状态更新是通过方法完成的。这是 class 组件中非常常见的模式。第一件事是用一个同名的函数组件包装它,将它的所有属性委托给包装的组件。您还需要在函数 return 中渲染包装的组件。这是:

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

    inc() {
      this.setState(prev => ({count: prev.count+1}));
    }

    render() {
      return <button onClick={() => this.inc()}>{this.state.count}</button>
    }
  }
  return <Hello {...props}/>
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

这是完全相同的组件,具有相同的行为、相同的名称和相同的属性。现在让我们将计数状态提升到函数组件。事情是这样的:

function Hello(props) {
  const [count, setCount] = React.useState(0);
  class Hello extends React.Component {
    constructor(props) {
      super(props);
      this.state = { count: props.count };
    }

    inc() {
      this.setState(prev => ({count: prev.count+1}));
    }

    render() {
      return <button onClick={() => setCount(count+1)}>{count}</button>
    }
  }
  return <Hello {...props}/>
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script>
<div id='root'></div>

请注意,方法inc 仍然存在,它不会伤害任何人,实际上是死代码。思路就是这样,不断提升state。完成后,您可以删除 class 组件:

function Hello(props) {
  const [count, setCount] = React.useState(0);

  return <button onClick={() => setCount(count+1)}>{count}</button>;
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script>

<div id='root'></div>

虽然这使得在 class 组件中使用挂钩成为可能,但我不建议您这样做,除非您像我在本例中那样进行迁移。混合函数和 class 组件会使状态管理变得一团糟。希望对您有所帮助

此致

谢谢 loelsonk,我这样做了

const [dataAction, setDataAction] = useState({name: '', description: ''});

    const _handleChangeName = (data) => {
        if(data.name)
            setDataAction( prevState  => ({ ...prevState,   name : data.name }));
        if(data.description)
            setDataAction( prevState  => ({ ...prevState,   description : data.description }));
    };
    
    ....return (
    
          <input onChange={(event) => _handleChangeName({name: event.target.value})}/>
          <input onChange={(event) => _handleChangeName({description: event.target.value})}/>
    )

useState 是一个钩子,可让您将状态添加到功能组件。它接受一个参数,该参数是状态 属性 的初始值和 returns 状态 属性 的当前值以及能够更新该状态的方法 属性.
下面是一个简单的例子:

import React, { useState } from react    

function HookCounter {    
  const [count, setCount]= useState(0)    
    return(    
      <div>     
        <button onClick{( ) => setCount(count+1)}> count{count}</button>    
      </div>    
    )   
 }

useState 接受状态变量的初始值(在本例中为零)和 returns 一对值。状态的当前值称为计数,可以更新状态变量的方法称为 setCount。

基本上 React.useState(0) 神奇地看到它应该 return 元组 countsetCount (一种更改 count 的方法)。参数useState take 设置初始值count.

  const [count, setCount] = React.useState(0);
  const [count2, setCount2] = React.useState(0);

  // increments count by 1 when first button clicked
  function handleClick(){
    setCount(count + 1);
  } 

  // increments count2 by 1 when second button clicked
  function handleClick2(){
    setCount2(count2 + 1);
  } 

  return (
    <div>
      <h2>A React counter made with the useState Hook!</h2>
      <p>You clicked {count} times</p>
      <p>You clicked {count2} times</p>
      <button onClick={handleClick}>
        Click me
      </button> 
      <button onClick={handleClick2}>
        Click me2
      </button>
  );

基于 Enmanuel Duran 的示例,但显示了两个计数器并将 lambda 函数编写为普通函数,因此有些人可能更容易理解。

上面提供的答案很好,但让我补充一下,useState 是异步的,所以如果您的下一个状态取决于您之前的状态,最好您传递 useState 一个回调。请参阅以下示例:

import { useState } from 'react';

function Example() {
    const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      // passing a callback to useState to update count
      <button onClick={() => setCount(count => count + 1)}>
        Click me
      </button>
    </div>
  );
}

如果您的新状态依赖于旧状态的计算,这是推荐的方法。

useState 是一个 Hook,它允许您在功能组件中拥有状态变量。

React 中有两种类型的组件:class 和功能组件。

Class 组件是从 React.Component 扩展而来的 ES6 classes,并且可以具有状态和生命周期方法:

class Message extends React.Component {
constructor(props) {
super(props);
this.state = {
  message: ‘’    
 };
}

componentDidMount() {
/* ... */
 }

render() {
return <div>{this.state.message}</div>;
  }
}

函数式组件是只接受参数作为组件属性的函数,return 有效的 JSX:

function Message(props) {
  return <div>{props.message}</div>
 }
// Or as an arrow function
const Message = (props) =>  <div>{props.message}</div>

如您所见,没有状态或生命周期方法。

React useState 是 React Hook,可让您管理功能组件内的状态。

例如:

import React, { useState } from 'react'

const Example = () => {
  // create the "counter" state
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>Button clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Count + 1
      </button>
    </div>
  )
}

export default Example

使用 useState,您可以轻松创建有状态的功能组件。 旧的等效方法,使用 class 组件与 Component class 和 setState 是:

import React, { Component } from 'react'

class Example extends Component {
  constructor(props) {
    super(props)
    this.state = { count: 0 }
  }

  render() {
    const { count } = this.state
    return (
      <div>
        <p>Button clicked {count} times</p>
        <button onClick={() => this.setState({ count: count + 1 })}>
          Count + 1
        </button>
      </div>
    )
  }
}

export default Example

来源:

链接:

让我们以简单的方式非常容易地理解useState

假设我们有反应代码:-

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Test from './components/Test.jsx'
ReactDOM.render(
  <div>
      <Test />
  </div>
,
  document.getElementById('root')
);

Test.jsx

import React from "react";

function Test() {
  var x = 5;
  function update() {
    console.log(x);
    return x++;
  }
  return (
    <div>
      <h1>{x}</h1>
      <button onClick={update}>click</button>
    </div>
  );
}
export default Test;

这里,页面会显示 5 ,虽然我们通过点击按钮调用更新功能,因为我们更新了 x 但不是在 h1 标签之间,但实际上, x 是不断变化的每当我们点击但它可以在控制台上看到

see result and check console by clicking this link

这里 usState 神奇地工作,

Test.jsx 使用 useState

import React, { useState } from "react";

function Test() {
  var x = 5;
  const [value, setValue] = useState(x);

  function update() {
    setValue(value + 1);
  }

  return (
    <div>
      <h1>{value}</h1>
      <button onClick={update}>click</button>
    </div>
  );
}
export default Test;

see result by clicking this link

这里,通过点击按钮,值会不断更新,因为这里我们使用了 useState ,它是一个 return 2 东西之一的函数 current state value 另一个是 function ,如果我们将任何值传递给这个 function 它将更新 current state vluecurrent state value 在所有使用的地方更新它的值,而无需编写任何额外的代码。