React 中的 useState() 是什么?

新手上路,请多包涵

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

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>

原文由 Hemadri Dasari 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 953
2 个回答

React 钩子 是一种新方法(仍在开发中),无需使用类即可访问诸如 state 之类的反应核心功能,在您的示例中,如果您想直接在处理程序函数中增加计数器而不直接在 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) 返回一个元组,其中第一个参数 count 是计数器的当前状态,而 setCounter 是允许我们更新计数器状态的方法。我们可以在任何地方使用 setCounter 方法来更新 count 的状态——在这种情况下,我们在 setCount 函数内部使用它,我们可以做更多的事情;使用钩子的想法是,如果不需要/不需要,我们能够使我们的代码更具功能性并避免 _基于类的组件_。

我写了一篇关于钩子的完整文章,其中包含多个示例(包括计数器),例如 这个 codepen ,我使用了 useStateuseEffectuseContext 和 _自定义钩子_。我可以详细了解钩子在这个答案上的工作原理,但是文档很好地详细解释了 状态钩子 和其他钩子,希望对您有所帮助。

更新: Hooks 不再是一个提案,因为 16.8 版它们现在可以使用,React 网站中有一个部分回答了一些 常见问题解答

原文由 Enmanuel Duran 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

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

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

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

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

setState 函数用于更新状态。它接受一个新的状态值并将组件的重新渲染排入队列。

请注意 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>

与类组件中的 setState 方法不同,useState 不会自动合并更新对象。您可以通过将函数更新器形式与对象传播语法相结合来复制此行为:

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

有关 useState 的更多信息,请参阅 官方文档

原文由 loelsonk 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题