Javascript 为什么在声明我的状态后,我的React渲染两次?

Javascript 为什么在声明我的状态后,我的React渲染两次?,javascript,reactjs,state,Javascript,Reactjs,State,我的React项目似乎在调用console.log并将其设置为2x后将我注意到的所有内容呈现两次。当我第一次在我的应用程序中声明状态时,似乎发生了这种情况,状态呈现之前的一个日志是2x后的一个日志 另外,声明状态后的componentDidMount只呈现一次 import React, { Component } from "react"; import { getProteins } from "./services/proteinsService"; import ProteinBuild

我的React项目似乎在调用console.log并将其设置为2x后将我注意到的所有内容呈现两次。当我第一次在我的应用程序中声明状态时,似乎发生了这种情况,状态呈现之前的一个日志是2x后的一个日志

另外,声明状态后的componentDidMount只呈现一次

import React, { Component } from "react";
import { getProteins } from "./services/proteinsService";
import ProteinBuilder from "./containers/ProteinToolbar/ProteinBuilder.jsx";
import BlendOutput from "./containers/BlendOutput/BlendOutput";
import "./App.css";

console.log("App before state");
class App extends Component {
  state = { proteins: getProteins() };
  componentDidMount() {
    console.log("componentDidMount");
  }

  render() {
    console.log("App after state");
    return (
      <div className="container">
        <div className="row">Nav</div>
        <div className="row">
          <div className="col col-sm-3">
            <ProteinBuilder proteins={this.state.proteins} />
          </div>
          <div className="col-sm-9">
            <div className="row">
              <div className="col-12 BlendOutput  border rounded">
                <BlendOutput proteins={this.state.proteins} />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default App;

React两次调用一些方法,如render方法,以帮助程序员捕捉错误方法中的错误实践,如API调用和其他副作用

ComponentDidMount是产生副作用的合适场所,因此React只需调用一次即可

有关更多信息,请查看此处:
React调用一些方法,如两次render方法,以帮助程序员捕捉错误方法中的错误做法,如API调用和其他副作用

ComponentDidMount是产生副作用的合适场所,因此React只需调用一次即可

有关更多信息,请查看此处:

蛋白质:不建议使用Get蛋白质。 我建议你这样做:

组件安装{ 这个.setState{proteins:getProteins}; }

无论何时更新状态或更改道具,都会调用render方法。

蛋白质:不建议使用getProteins。 我建议你这样做:

组件安装{ 这个.setState{proteins:getProteins}; }


无论何时更新状态或更改道具,都会调用render方法。

我在下面的代码段中创建了案例的简化版本,如果从未调用setState,则不会看到相同的行为。因此,我认为问题在于:

子组件正在调用setState,并导致重新渲染 父组件正在导致重新渲染 您已启用。 此片段详细介绍了渲染生命周期中发生的情况。注释掉设置状态的部分,您就有了一个与您发布的示例相同的示例,减去子组件

console.log创建应用程序组件; 函数setFoo{console.log'settingfoo';返回'bar'} 类应用程序扩展了React.Component{ state={foo:setFoo}; 组件安装{ console.logcomponentDidMount.Current状态,this.state; 这是我的国家 {qux:'quo'}, =>console.log“setState回调set state已完全应用has state”,this.state console.logcomponentDidMount->this.setState已调用,但可能尚未应用。当前状态为this.state } 渲染{ console.logApp.render with state,this.state; 回来 {JSON.stringifythis.state} ; } } console.log“在dom呈现之前” ReactDOM.render,document.getElementById'app' console.log'after dom render'
我在下面的代码片段中创建了您案例的简化版本,如果从未调用setState,则不会看到相同的行为。因此,我认为问题在于:

子组件正在调用setState,并导致重新渲染 父组件正在导致重新渲染 您已启用。 此片段详细介绍了渲染生命周期中发生的情况。注释掉设置状态的部分,您就有了一个与您发布的示例相同的示例,减去子组件

console.log创建应用程序组件; 函数setFoo{console.log'settingfoo';返回'bar'} 类应用程序扩展了React.Component{ state={foo:setFoo}; 组件安装{ console.logcomponentDidMount.Current状态,this.state; 这是我的国家 {qux:'quo'}, =>console.log“setState回调set state已完全应用has state”,this.state console.logcomponentDidMount->this.setState已调用,但可能尚未应用。当前状态为this.state } 渲染{ console.logApp.render with state,this.state; 回来 {JSON.stringifythis.state} ; } } console.log“在dom呈现之前” ReactDOM.render,document.getElementById'app' console.log'after dom render'
你在状态后两次得到应用程序?是的,状态后的应用程序记录两次,状态前的应用程序记录两次你说你的应用程序呈现两次?您是否已检查问题是否来自父组件?它可以呈现两次子对象。两次在状态后获取应用程序?是的,两次在状态后获取应用程序日志,以及两次在状态前获取应用程序渲染?您是否已检查问题是否来自父组件?它可以呈现两次子对象。这是我不知道的一个整洁的特性,但默认情况下它不是活动的。你必须使用StrictMode组件并包装你想要检查的应用程序部分。因为我怀疑OP是否在使用这个组件,这可能不是问题所在。@GarrettMotzner实际上可能会在没有任何明显原因的情况下任意多次调用render方法,程序员应该以一种不会破坏任何东西的方式编程。但既然他说了两次,我想我的回答会对他有所帮助。同意,因此,让render非幂等式有副作用的糟糕做法,但这里的问题是为什么,这不是原因

好的,嗯,我确实激活了这个模式。我禁用了它,但我仍然有问题。一个问题是,当我在某些元素上循环时,它们会创建重复的键值,从而抛出error@HPylori正如我告诉您的,React不能保证调用render方法的次数。您必须以不会产生问题的方式编写代码。我建议您关闭此问题,因为您找到了多次渲染的原因。然后打开另一个问题,并将您的新问题与其错误消息一起分享。你可以在这里分享你的问题链接,这样我就可以查看它了。这是一个我不知道的好功能,但默认情况下它是不活动的。你必须使用StrictMode组件并包装你想要检查的应用程序部分。因为我怀疑OP是否在使用这个组件,这可能不是问题所在。@GarrettMotzner实际上可能会在没有任何明显原因的情况下任意多次调用render方法,程序员应该以一种不会破坏任何东西的方式编程。但既然他说了两次,我想我的回答会对他有所帮助。同意,因此,让render非幂等式有副作用的糟糕做法,但这里的问题是为什么,这不是afaik的原因。嗯,我确实激活了。我禁用了它,但我仍然有问题。一个问题是,当我在某些元素上循环时,它们会创建重复的键值,从而抛出error@HPylori正如我告诉您的,React不能保证调用render方法的次数。您必须以不会产生问题的方式编写代码。我建议您关闭此问题,因为您找到了多次渲染的原因。然后打开另一个问题,并将您的新问题与其错误消息一起分享。你可以在这里分享你的问题链接,这样我就可以看了。我的index.js有:`-我把它们改成了碎片,但我仍然得到了一个加倍的渲染-我现在没有在任何子组件中调用setState。那么它会是我的父组件中的其他东西吗?是的,我想它会是你的设置中的一些微妙的东西。片段不应该导致双重渲染,但React.StrictMode肯定会。如果只获得一个双渲染,则可以忽略它,但如果总渲染周期变得足够复杂,则以后可能会出现性能问题,因为这是顶级的,所以更重要。我会尝试删除部分代码,如果这会改变它,然后将它们放回原处,如果您真的想跟踪问题,则删除其他部分。不过,主要的收获是react调用render非常自由,而且它的设计使它可以在需要时以最低的成本调用render,如果您使用的是开发版本,那么您可以尝试使用react的prod版本进行双重检查。有时候开发人员的功能会做这样的事情。我的index.js有:`-我把它们改成了片段,但我仍然得到了加倍的渲染-我现在没有在任何子组件中调用setState。那么它会是我的父组件中的其他东西吗?是的,我想它会是你的设置中的一些微妙的东西。片段不应该导致双重渲染,但React.StrictMode肯定会。如果只获得一个双渲染,则可以忽略它,但如果总渲染周期变得足够复杂,则以后可能会出现性能问题,因为这是顶级的,所以更重要。我会尝试删除部分代码,如果这会改变它,然后将它们放回原处,如果您真的想跟踪问题,则删除其他部分。不过,主要的收获是react调用render非常自由,而且它的设计使它可以在需要时以最低的成本调用render,如果您使用的是开发版本,那么您可以尝试使用react的prod版本进行双重检查。有时候开发功能会这样做。这并不能为我正确地创建状态,当我使用它时,子组件的道具为null。我应该使用不同的生命周期挂钩吗?这不会为我正确创建状态,当我使用它时,子组件的道具为null。我应该使用不同的生命周期挂钩吗?
const proteins = [
  {
    _id: 1,
    name: "Pea Protein Isolate",
    description: "Pea Protein Isolate",
    digestibility: 0.98,
    AA: {
      His: 2.5,
      Ile: 4.5,
      Leu: 8.4,
      Lys: 7.2,
      MetCys: 2.1,
      PheTyr: 9.3,
      Thr: 3.9,
      Trp: 1,
      Val: 5
    },
    percentOfBlend: 0.382
  },

  {
    _id: 2,
    name: "Texturized Pea Protein",
    description: "Texturized Pea Protein",
    digestibility: 0.94,
    AA: {
      His: 2.0,
      Ile: 3.91,
      Leu: 6.84,
      Lys: 5.96,
      MetCys: 2.69,
      PheTyr: 7.31,
      Thr: 3.02,
      Trp: 0.84,
      Val: 4.23
    },
    percentOfBlend: 0.448
  },

  {
    _id: 3,
    name: "Sacha Inchi Protein",
    description: "Sacha Inchi",
    digestibility: 0.92,
    AA: {
      His: 2.6,
      Ile: 5,
      Leu: 6.4,
      Lys: 4.3,
      MetCys: 3.7,
      PheTyr: 7.9,
      Thr: 4.3,
      Trp: 2.9,
      Val: 4
    },
    percentOfBlend: 0.17
  },

  {
    _id: 4,
    name: "Potato Protein",
    description: "Potato protein isolate",
    digestibility: 0.95,
    AA: {
      His: 1.7,
      Ile: 5.6,
      Leu: 9.2,
      Lys: 7.1,
      MetCys: 3.2,
      PheTyr: 11.6,
      Thr: 4.4,
      Trp: 1.4,
      Val: 8
    },
    percentOfBlend: 0.0
  }
];

export function getProteins() {
  return proteins;
}

export function multiplyProteins() {
  proteins.map(proteins.AA.map());
}