简体   繁体   English

React中setState的这两种更新函数是否相等?

[英]Are these two types of updater functions for setState in React equal?

I've recently learned about updater functions for setState in React. 我最近在React中了解了setState updater函数

And now I've seen this concept used in two different ways. 现在我已经看到这个概念以两种不同的方式使用。 Let's say we have a state object like this: 假设我们有一个像这样的状态对象:

interface State {
  readonly expanded: boolean;
  readonly slugs: string[];
}

state: State = { expanded: false, slugs: [] }

I have seen updater functions used like this: 我见过如下使用的updater函数:

this.setState(prevState => ({ ...prevState, expanded: !prevState.expanded }));

And like this: 像这样:

this.setState(({ expanded }) => ({ expanded: !expanded }));

I've tried this out myself to see if there is a difference between using the two, but I couldn't find one (besides the amount of characters 😄). 我自己试了一下,看看两者之间是否有区别,但我找不到一个(除了字符数量😄)。 My intuition just tells me that the first way might be more safe because the second way state (in this case slugs ) might be overwritten? 我的直觉告诉我,第一种方式可能更安全,因为第二种方式state (在这种情况下是slugs )可能会被覆盖?

Edit: This questions has been flagged as a duplicate of this question , but it is inherently different, because I was wondering about the functionalities of setState and not about how TypeScript's type annotation works. 编辑:这个问题已被标记为此问题的副本,但它本质上是不同的,因为我想知道setState的功能,而不是关于TypeScript的类型注释是如何工作的。 I merely provided the TypeScript types for clarity. 为清楚起见,我只提供了TypeScript类型。 I'm sorry this question caused confusion. 对不起,这个问题引起了混乱。 English is not my main language and I didn't know how to express this more clearly. 英语不是我的主要语言,我不知道如何更清楚地表达这一点。 Luckily someone understood and answered the question perfectly. 幸运的是,有人理解并完美地回答了这个问题。

If you look into the source code, especially into setState and enqueueSetState , you can see the following piece of code: 如果你查看源代码,特别是进入setStateenqueueSetState ,你可以看到以下代码:

if (typeof partialState === 'function') {
  partialState = partialState.call(
    pu blicInstance,
    currentState,
    publicInstance.props,
  );
}

// Null and undefined are treated as no-ops.
if (partialState === null || partialState === undefined) {
  return;
}

this._renderer._newState = {
  ...currentState,
  ...partialState,
};

What that means is that 这意味着什么

this.setState(({ expanded }) => ({ expanded: !expanded }));

will end up being: 最终将成为:

state = {...prevState, {expanded: !expanded}}

and

this.setState(prevState => ({ ...prevState, expanded: !prevState.expanded }));

will end being: 将结束:

 state = {...prevState, ...{...prevState, expanded: !prevState.expanded}}

I think the second one is basically poor understanding on how the updater function works. 我认为第二个基本上是对updater功能如何工作的理解不足。

正如React的官方文档状态更新被合并所说,React会将您提供的对象合并到当前状态,而不是覆盖整个状态。

Both the statement would result in the same behavior - updation of expanded value. 这两个语句都会导致相同的行为 - expanded值的更新。 If you read through the setState method's documentation, React expect the method to return the value that needs to be overridden. 如果您通读了setState方法的文档,React希望该方法返回需要重写的值。 React merges the return of the method to the previous state object and does a diff. React将方法的返回合并到先前的状态对象并执行diff。 In the first clause, all the other state variables are the same, except the expanded and in the second clause, only expanded is mutated. 在第一个子句中,所有其他状态变量都是相同的,除了expanded和第二个子句之外,只expanded变异。

To understand with the second code, you may look in attached duplicate post , but I found your case a little bit different. 要理解第二个代码,您可以查看附加的重复帖子 ,但我发现您的案例有点不同。 Thus, answering here. 因此,在这里回答。

this.setState(prevState => ({ ...prevState, expanded: !prevState.expanded }));

Here, the use of ...prevState is just unnecessary. 在这里,使用...prevState是不必要的。 It's because react's setState handles the particular state and merge other states. 这是因为react的setState处理特定状态并合并其他状态。

this.setState(prevState => ({ expanded: !prevState.expanded }));

You'll only need to use merging when you'll need to update the properties nested in the particular state. 当您需要更新嵌套在特定状态的属性时,您只需要使用合并。 For example, if you have something like: 例如,如果你有类似的东西:

state = {
  people: {
   male: 1033,
   female: 234,
   other: 100
  }
}

Now, in this case you may merge people value when you only update the male count like: 现在,在这种情况下,当您仅更新男性计数时,您可以合并人员值:

this.setState(prevState => ({ people: { ...prevState.people, male: 1045 } }))

Which can simply be written destructuring like: 这可以简单地写成解构,如:

this.setState(({people}) => ({ people: { ...people, male: 1045 } })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM