react + useState() + previousState

IT技术 javascript reactjs react-hooks
2021-05-03 11:48:46

我是个新手,在理解 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?并传入初始状态的参数(initialCount)
  • 我得到一个数组,我立即将其销毁为变量 count 和 setCount(这是函数)
  • 使用 setCount() 我可以更新状态,从而更新计数变量

到目前为止一切顺利,我认为... ;)

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

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

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

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

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

非常感谢您的帮助。

2个回答

首先,你可以在这里看到官方的解释

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

您没有以某种方式访问先前的计数值。如果您使用功能更新并向 setter 提供回调函数,它会将之前的状态返回给您,您可以在回调函数中使用此值。

setCount 现在需要一个函数

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

setCount 现在异步运行

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

这个函数从哪里来?

prevCount 来自哪里?

已经回答了。

当我运行这个时,什么被放入 prevCount?

您提供要在那里设置新状态的内容。在您的示例中,您希望增加count1,因此您提供+ 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(无分型):

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并根据该类型进行操作最后,这是useReducer 返回的内容

return [workInProgressHook.memoizedState, dispatch];

所以,在一天结束时,如果我们向 提供一个函数useState,它接受它,然后在我们的状态上运行它并返回值。

这是我的看法,我是如何理解的:

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

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

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

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

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

当我运行这个时,什么被放入 prevCount? -> setCount 的当前状态。

=> 此处如何将值或回调传递给 setCount 的示例:useState 钩子、setState 函数。访问先前的状态值