【问题标题】:React Strict Mode反应严格模式
【发布时间】:2021-09-28 14:06:59
【问题描述】:

我正在处理我的项目,我注意到当打开严格模式时,它会将两个相同的元素推送到我的数组中。当严格模式关闭时,它只会将一个元素推入数组。有什么解释为什么会这样吗?

import {getRandomNumber} from './utils';


export function registerTicket() {
    const newTicket = {
        number: getRandomNumber(),
        color: 'red',
    }
    this.setState((prevState) => {
        prevState.tickets.push(newTicket);
        return {
            remainingTickets: --prevState.remainingTickets,
            tickets: prevState.tickets,

        }
    })
}

这是我的状态。

    this.state = {
      winningNumber: getRandomNumber(),
      remainingTickets: 5,
      tickets: [],
      finished: false
    };

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

React StrictMode 通过有意地重复调用某些生命周期方法和 React 钩子来帮助暴露无意的副作用。 setState updater 函数是一个被调用两次的函数。我将深入解释链接的问题。

Detecting unexpected side-effects

当您将新元素推入其中时,您的无意副作用是先前 tickets 状态的状态突变,当您预先减少 @987654326 @ 状态。帽子戏法是您也不返回新的 tickets 数组引用。

this.setState((prevState) => {
  prevState.tickets.push(newTicket); // <-- mutation!!
  return {
    remainingTickets: --prevState.remainingTickets, // <-- mutation!!
    tickets: prevState.tickets, // <-- same old array reference
  }
})

解决方法是将之前的状态数组浅拷贝到新的数组引用中,并追加新元素。

this.setState((prevState) => ({
  remainingTickets: prevState.remainingTickets - 1,
  tickets: [...prevState.tickets, newTicket],
}));

【讨论】:

  • 哦,所以 setstate 被调用了两次?
  • @ProHunter67 传递给setState 的回调函数被调用了两次,但本质上,是的,这就是效果。
  • @ProHunter67 因为你没有改变任何东西。在两次调用中,您都将相同的更新应用于相同的先前状态,每次的结果都是相同的。
  • @ProHunter67 是的。把它想象成 React 只是调用更新器函数计算下一个状态(这就是它实际上是什么)两次,但只存储下一次渲染的结果一次。如果函数中的副作用为零,那么您会看到与仅调用一次相同的结果。 BUT 如果存在副作用和/或突变,这些可能会泄漏并暴露出来。第一次调用执行了array.push 并改变了先前的状态,然后第二次调用执行了另一个array.push 并再次对其进行了变异,然后在下一次渲染中,您会看到两次推送的结果。
  • @ProHunter67 是的,确认了here 的行为。 TBH 我认为您寻求的答案在于 ReactDOM 和协调代码,以了解它如何处理状态更新器函数和 StrictMode。我的大部分知识来自文档和经验。
【解决方案2】:

React.StrictMode 导致渲染函数在开发过程中被调用两次,以识别意外的副作用

【讨论】:

    猜你喜欢
    • 2020-11-07
    • 2023-01-31
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-19
    • 2019-07-08
    • 2011-09-11
    相关资源
    最近更新 更多