【问题标题】:React + useState() + previousState反应 + useState() + previousState
【发布时间】:2020-12-30 07:27:34
【问题描述】:

我对反应非常陌生,并且在理解 useState Hook 方面存在问题 - 或者更具体地说是 previousState 的方面。

一个普通的 useState Hook,可能是最常见的例子,如下所示:

import React, { useState} from 'react';

export default function CounterHooks({ initialCount }){
  const [count, setCount] = useState(initialCount);

  return (
    <div>
      <button onClick={() => setCount(count -1)}>-</button>
      <span>{count}</span>
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  )
}

目前我的理解如下:

  • 我调用 useState() 函数/Hook?并传入初始State(initialCount)的参数
  • 我取回了一个数组,我立即将其分解为变量 count 和 setCount(其中 是函数)
  • 使用 setCount() 我可以更新状态,从而更新计数变量

到目前为止一切都很好,我认为... ;)

有时我会看到与 prevState (prevCount) 相同的反例,但我不明白:

<button onClick={() => setCount(prevCount => prevCount -1)}>-</button>

这里发生了什么?这部分我不明白。 到目前为止我的想法:

  • 在这种情况下,我以某种方式访问​​了之前的计数值。
  • setCount 现在需要一个函数
  • setCount 现在异步运行
  • 这个函数是从哪里来的?
  • prevCount 来自哪里?
  • 当我运行此程序时,prevCount 中放入了什么?

你明白我的困惑吗?我不知道我应该如何以不同的方式构建这个......

非常感谢您的帮助。

【问题讨论】:

  • 你说的都是对的。 state setter 函数可以接收一个函数而不是一个值。如果 setter 接收到一个函数,它将调用该函数来设置具有函数返回值的状态。此外,它会将previousState 作为参数传递给该函数。这是您可以根据先前状态更改状态的方法。请在此处找到更详细的答案:stackoverflow.com/questions/56404819/…
  • 您好安德烈,感谢您的帮助。我在文档中阅读了这一点,但我不明白:reactjs.org/docs/hooks-reference.html#functional-updates。我不明白的是:我将什么函数传递给 setState()/setCount()。
  • “我不明白的是:我将什么函数传递给 setState()/setCount()。” 一个接受单个参数的函数(之前的值)并返回新值(可能基于也可能不基于先前的值)。也许关于 setState 的文档使它更清晰(接近尾声):reactjs.org/docs/react-component.html#setstate。如果新状态不依赖于前一个状态,则无需传递函数。

标签: javascript reactjs react-hooks


【解决方案1】:

首先可以看官方解释here。

在这种情况下,我以某种方式访问​​了之前的计数值。

您没有以某种方式访问之前的计数值。如果你使用函数更新并给 setter 一个回调函数,它会返回之前的状态给你,你在你的回调函数中使用这个值。

setCount 现在需要一个函数

既然你提供了一个函数,它就可以使用它。

setCount 现在异步运行

实际上,没有。它不是一个异步函数。它只是提供以前的状态,您可以使用它。状态设置器不是异步的,状态更新是异步的。

这个函数是从哪里来的?

prevCount 来自哪里?

已经回答了。

当我运行它时,prevCount 中会放入什么?

你提供你想在那里设置的新状态。在您的示例中,您希望将 count 增加 1,因此您提供 + 1

这是对这种逻辑的幼稚解释。只是一个天真的。 我添加这个是为了举例说明回调逻辑,这个和React的setState.无关

let state = 5;

function setState(val) {
  if (typeof val === "function") {
    return val(state);
  }

  return val;
}

const stateWithFunctionalUpdate = setState(prev => prev + 1);
const stateWithNormalUpdate = setState(9);
console.log(stateWithFunctionalUpdate);
console.log(stateWithNormalUpdate);

也许这个例子适合模仿 React 的状态设置逻辑。同样,这只是一种幼稚的方法。

let state = 5;

function setState(val) {
  if (typeof val === "function") {
    state = val(state);
  } else {
    state = val;
  }

}

setState(9);
setState(prev => prev + 1);

console.log("state", state);

让我们看看useState 的real implementation(没有打字):

export function useState(initialState) {
  return useReducer(
    basicStateReducer,
    // useReducer has a special case to support lazy useState initializers
    initialState
  );
}

嗯,它只是在窗帘后面使用useReducer。它设置初始状态并使用basicStateReducer,即:

function basicStateReducer(state, action) {
  return typeof action === "function" ? action(state) : action;
}

就像我们的幼稚方法一样,它会查找action 的类型并据此行事。最后,这是useReducerreturns:

return [workInProgressHook.memoizedState, dispatch];

因此,归根结底,如果我们向useState 提供一个函数,它会接受它,然后在我们的状态上运行它并返回值。

【讨论】:

  • 您好 devserkan,非常感谢您的详细回复。这很有帮助。我想我现在明白了。我将回调函数传递给 useState。 useState 调用该函数。回调函数需要一个参数,setCount 提供变量 count 的值。
  • 不客气。好吧,你几乎是对的。您没有将回调传递给useState,而是传递给setState、setCounter 或任何setter :)
【解决方案2】:

以下是我的理解:

在这种情况下,我以某种方式访问​​了之前的计数值。 -> setCount 将检查参数,如果参数是回调,它将调用该回调并传递参数的先前状态。回调的结果将是下一个状态。

setCount 现在需要一个函数 -> 是的,函数处理你的逻辑并返回下一个状态。

setCount 现在异步运行 -> 这个函数是同步的,但是在它返回结果之后。 setCount 的钩子会派发事件来更新下一个状态

这个函数是从哪里来的? -> 只要参数是当前状态并返回下一个状态,您就可以在函数中做任何事情。

prevCount 来自哪里? -> 调用 setCount 时会传递(从当前状态获取)。

当我运行这个时,prevCount 中的内容是什么? -> setCount 的当前状态。

=> 如何在此处将值或回调传递给 setCount 的示例:useState hook, setState function. Accessing previous state value

【讨论】:

    猜你喜欢
    • 2021-07-12
    • 2021-04-11
    • 2020-06-20
    • 1970-01-01
    • 2023-03-23
    • 2021-08-20
    • 2022-01-09
    • 2019-10-20
    • 2021-03-07
    相关资源
    最近更新 更多