Почему мой React рендерит дважды после объявления моего состояния? - PullRequest
0 голосов
/ 01 апреля 2020

Кажется, что мой проект 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;

My getProteins () получает следующие данные:

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());
}

Ответы [ 3 ]

1 голос
/ 01 апреля 2020

proteins: getProteins() не рекомендуется. Я предлагаю вам сделать это:

componentDidMount(){ this.setState({proteins: getProteins()}); }

и метод render() вызывается при каждом обновлении состояния или изменении реквизита.

1 голос
/ 01 апреля 2020

Я создал упрощенную версию вашего дела в приведенном ниже фрагменте кода и не видел того же поведения, если setState никогда не вызывался. Поэтому я думаю, что проблема заключается в одном из:

  • дочерний компонент вызывает setState и вызывает повторную визуализацию
  • родительский компонент вызывает повторную визуализацию
  • у вас есть StrictMode .

Этот фрагмент дает представление о жизненном цикле рендеринга. Закомментируйте раздел, который устанавливает состояние, и у вас есть пример, который должен совпадать с тем, что вы опубликовали, за исключением дочерних компонентов.

console.log("create App component");
function setFoo(){console.log('setting foo'); return 'bar'}
class App extends React.Component {
  state = { foo: setFoo() };
  componentDidMount() {
    console.log("componentDidMount. Current state", this.state);
    this.setState(
      {qux: 'quo'}, 
      () => console.log('setState callback (set state has been fully applied) has state', this.state)
    )
    console.log("componentDidMount -> this.setState() was called (but may not have been applied). Current state", this.state)
  }

  render() {
    console.log("App.render() with state", this.state);
    return (
      <div>
        {JSON.stringify(this.state)}
      </div>
    );
  }
}

console.log('before dom render')
ReactDOM.render(<App/>, document.getElementById('app'))
console.log('after dom render')
<div id="app" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Если вы хотите поэкспериментировать с фрагментом, вы также можете попробовать вызвать setState несколько раз подряд и посмотреть, что происходит с состоянием после каждого звонка.

0 голосов
/ 01 апреля 2020

React дважды вызывает некоторые методы, такие как метод рендеринга, чтобы помочь программистам уловить неправильные методы, такие как вызовы API и другие побочные эффекты в неправильных методах.

ComponentDidMount - правильное место для побочных эффектов, поэтому React вызывает его один раз .

Для получения дополнительной информации проверьте здесь: https://reactjs.org/docs/strict-mode.html#detecting - неожиданные побочные эффекты

...