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

当前回答

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

虽然不能在类内部使用钩子,但可以用函数1包装类组件并从中使用钩子。这是将组件从类形式迁移到函数形式的一个很好的工具。下面是一个完整的例子:

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

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>

它是一个具有计数状态的简单类组件,状态更新由方法完成。这是类组件中非常常见的模式。第一件事是用同名的函数组件包装它,该函数组件将其所有属性委托给被包装的组件。此外,您还需要在函数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仍然在那里,它不会伤害任何人,实际上是死代码。就是这样,不断提升状态。一旦你完成,你可以删除类组件:

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>

虽然这使得在类组件中使用钩子成为可能,但我不建议您这样做,除非您像我在本例中那样迁移。混合函数和类组件将使状态管理变得混乱。我希望这对你们有帮助

致以最亲切的问候

其他回答

让我们用简单的方式很容易地了解我们的用法

假设我们有react代码:-

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是不断变化的,每当我们点击,但它可以在控制台看到

点击此链接查看结果和检查控制台

在这里usState神奇地工作,

测试。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;

点击此链接查看结果

在这里,通过点击按钮,值将不断更新,因为这里我们使用useState,它是一个函数,它返回两件事,一个是当前状态值,另一个是函数,如果我们传递任何值给这个函数,它将更新当前状态值,当前状态值更新它的值在所有地方,无论它使用,而无需编写任何额外的代码。

钩子是React v16.7.0 alpha中的一个新特性,useState是“钩子”。useState()设置任意变量的默认值,并在函数组件(PureComponent函数)中进行管理。ex: const [count, setCount] = useState(0);设置默认值count 0。你可以使用setCount来增加或减少这个值。onClick={() => setCount(count + 1)}增加计数值

上面提供的答案很好,但让我插一句,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>
  );
}

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

谢谢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()是一个内置React钩子的例子,它允许你在函数组件中使用状态。这在React 16.7之前是不可能的。

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