【问题标题】:What is useState() in React?React 中的 useState() 是什么?
【发布时间】:2019-04-09 11:52:07
【问题描述】:

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

【问题讨论】:

标签: javascript reactjs react-native react-hooks react-state


【解决方案1】:

React hooks 是一种新方法(仍在开发中),无需使用类即可访问诸如 state 之类的 react 核心功能,在您的示例中,如果您想直接在处理函数中增加一个计数器而不指定它直接在 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 函数中使用它,我们可以做更多的事情;使用钩子的想法是,如果不需要/不需要,我们可以让代码保持更多功能并避免基于类的组件

I wrote a complete article about hooks with multiple examples(包括计数器)例如this codepen,我使用了useStateuseEffectuseContext自定义挂钩。我可以详细了解钩子在这个答案上的工作原理,但是文档很好地解释了state hook 和其他钩子,希望对您有所帮助。

更新: Hooks are not longer a proposal,由于版本 16.8 现在可以使用它们,React 网站中有一个部分回答了一些 FAQ .

【讨论】:

  • 很好的类比,只是 JavaScript 在技术上没有元组数据类型
  • 嗯,解构赋值像元组stackoverflow.com/a/4513061/6335029一样使用
  • 钩子是异步的吗?使用 setSomething 时,如果我之后尝试直接使用 something ,它似乎仍然具有旧值...
  • 钩子不会在“设置值”调用后更新它的值,直到重新渲染组件。 Hookstate (hookstate.js.org) 库的增压 useState 为您提供即时价值更新和更多功能。免责声明:我是该库的作者。
  • 您能否解释一下为什么我们将const 与肯定会改变的状态相关联? const count 我觉得很奇怪
【解决方案2】:

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 的更多信息,请参阅official documentation

【讨论】:

  • 感谢您在示例中添加函数作为参数。
  • 你的比较例子帮助像我这样的新手了解useState的用法
【解决方案3】:

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>
   );
 }

【讨论】:

  • 这应该是公认的答案。简洁明了,有良好的外部参考。
  • 这是最糟糕的答案,基本上是复制/粘贴文档页面。我来到这里是因为文档页面令人困惑
  • 朋友你有什么困惑?很难找到比官方文档更好的解释。
【解决方案4】:

useState 是 React v16.8.0 中可用的钩子之一。它基本上可以让您将原本无状态/功能性的组件转变为可以拥有自己状态的组件。

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

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

这让你调用setLoading 传递一个布尔值。 这是拥有“有状态”功能组件的一种很酷的方式。

【讨论】:

    【解决方案5】:

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

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

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

    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>

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

    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>

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

    最好的问候

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

        谢谢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})}/>
            )

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            【解决方案9】:

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

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

            useState 接受状态变量的初始值,在这种情况下为零,并返回一对值。状态的当前值被称为count,一个可以更新状态变量的方法被称为setCount。

            【讨论】:

              【解决方案10】:

              基本上React.useState(0) 神奇地看到它应该返回元组countsetCount(一种更改count 的方法)。 useState 的参数设置了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 函数编写为普通函数,因此有些人可能更容易理解。

              【讨论】:

                【解决方案11】:

                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,您可以轻松创建有状态的功能组件。 旧的等效方式,使用带有Component 类和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
                

                来源:

                链接:

                【讨论】:

                  【解决方案12】:

                  让我们以简单的方式很容易理解 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,它是一个返回2个东西的函数,一个是当前状态值,另一个是是 function ,如果我们向这个 function 传递任何值,它将更新 current state vluecurrent state value 更新无需编写任何额外代码,在任何地方使用它的值。

                  【讨论】:

                    【解决方案13】:

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

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

                    【讨论】:

                      【解决方案14】:

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

                      React 中有两种类型的组件:类和函数式组件。

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

                      class Message extends React.Component {
                      constructor(props) {
                      super(props);
                      this.state = {
                        message: ‘’    
                       };
                      }
                      
                      componentDidMount() {
                      /* ... */
                       }
                      
                      render() {
                      return <div>{this.state.message}</div>;
                        }
                      }
                      

                      函数式组件是只接受参数作为组件属性并返回有效 JSX 的函数:

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

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

                      【讨论】:

                        猜你喜欢
                        • 2020-06-21
                        • 2020-03-10
                        • 1970-01-01
                        • 2023-03-21
                        • 2019-08-08
                        • 2022-07-06
                        • 2022-01-06
                        相关资源
                        最近更新 更多