什么是 React 中的 useState()?

我目前正在 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>

答案 1

React 钩子是一种访问 react 核心功能的新方法(仍在开发中),例如无需使用类,在您的示例中,如果您想在处理程序函数中直接递增计数器而不直接在 prop 中指定它,您可以执行如下操作:stateonClick

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

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

和 onClick:

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

让我们快速解释一下这一行中发生了什么:

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

useState(0)返回一个元组,其中第一个参数是计数器的当前状态,并且是允许我们更新计数器状态的方法。我们可以使用该方法来更新任何地方的状态 - 在这种情况下,我们在函数内部使用它,我们可以做更多的事情;钩子的想法是,我们能够保持我们的代码更具功能性,并避免基于类的组件,如果不需要/不需要。countsetCountersetCountercountsetCount

我写了一篇关于钩子的完整文章,其中包含多个示例(包括计数器),例如此代码笔,我使用了,,和自定义钩子。我可以更详细地了解钩子如何在这个答案上工作,但文档在详细解释状态钩子和其他钩子方面做得很好,希望它有所帮助。useStateuseEffectuseContext

更新:钩子不再是一个提案,因为版本16.8它们现在可以使用,React的网站中有一个部分回答了一些FAQ


答案 2

useState是版本中可用的内置反应钩子之一。0.16.7

useState应仅在功能组件内部使用。 是我们需要内部状态并且不需要实现更复杂的逻辑(如生命周期方法)的方法。useState

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

返回一个有状态值,以及一个用于更新该值的函数。

在初始呈现期间,返回的状态(state)与作为第一个参数传递的值(initialState)相同。

setState 函数用于更新状态。它接受新的状态值,并将组件的重新呈现排入队列。

请注意,用于更新状态的钩子回调的行为与组件 不同。为了向您展示差异,我准备了两个例子。useStatethis.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>

使用回调时将创建新对象。请注意,我们丢失了键值。为了修复我们可以在 里面传递函数。setUserInfolastNameuseState

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>

与类组件中的 setState 方法不同,useState 不会自动合并更新对象。您可以通过将函数更新程序表单与对象展开语法相结合来复制此行为:

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

有关详情,请参阅官方文档useState