反应+useState()+PreviousState

2022-07-23 00:00:00 reactjs javascript react-hooks

我是个新手,在理解useState钩子--或者更具体地说是previousState方面--方面遇到了问题。

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

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(PremCount)相同的反例,这是我不理解的:

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

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

  • 在本例中,我以某种方式访问了上一个计数值。
  • setCount现在需要一个函数
  • setCount现在正在异步运行
  • 此函数来自哪里?
  • PrevenCount来自哪里?
  • 当我运行此操作时,PrevenCount中放入了什么?

你明白我的困惑吗?我不确定我应该如何用不同的方式来表述这一点...

非常感谢您的帮助。


解决方案

首先可以看到官方解释here。

在这种情况下,我以某种方式访问了上一个计数值。

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

setCount现在需要一个函数

既然您提供了函数,它就可以使用它。

setCount现在正在异步运行

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

此函数来自哪里?

预防计数从何而来?

已应答。

当我运行此操作时,PrevenCount中放入了什么?

您提供您希望在那里设置新状态的内容。在您的示例中,您希望将count递增1,因此您提供了+ 1

以下是对这一逻辑的一个天真解释。只是一个天真的问题。我添加这个是为了举例说明回调逻辑,这与Reaction的setState.

无关 数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
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);

可能此示例适用于模拟Reaction的状态设置逻辑。再说一次,这只是一种天真的做法。

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
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提供一个函数,它将获取该函数,然后在我们的状态上运行该函数并返回值。

相关文章