ComponentDidUpdate не работает

Я пытаюсь динамически визуализировать набор компонентов с помощью componentDidUpdate. Это мой сценарий:

var index = 0;

class myComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      componentList: [<ComponentToRender key = {index} id = {index} />]
    };

    this.addPeriodHandler = this.addPeriodHandler.bind(this);
  }

  componentDidUpdate = () => {
    var container = document.getElementById("container");
    this.state.componentList.length !== 0
      ? ReactDOM.render(this.state.componentList, container)
      : ReactDOM.unmountComponentAtNode(container);
  };

  addHandler = () => {
    var array = this.state.componentList;
    index++;
    array.push(<ComponentToRender key = {index} id = {index} />);
    this.setState = {
      componentList: array
    };
  };

  render() {
    return (
      <div id = "Wrapper">
        <button id = "addPeriod" onClick = {this.addHandler}>
          Add Component
        </button>
        <div id = "container" />
      </div>
    );
  }
}

Проблема в том, что componentDidUpdate работает только один раз, но он должен работать каждый раз при изменении состояния этого компонента. Заранее спасибо.

Правило №1 клуба React Club: никогда не изменяйте состояние / свойства.

PlayMa256 01.08.2018 16:24

Откуда берутся «компоненты для рендеринга»?

trixn 01.08.2018 16:31

Это компонент, который я импортирую из другой папки

M.Morris 01.08.2018 16:37

Но что в нем? Отображает ли он какие-либо данные?

trixn 01.08.2018 16:38

Он содержит четыре поля ввода

M.Morris 01.08.2018 16:47
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
83
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

пытаться

addHandler = () =>{
    var array = this.state.componentList.slice();
    index++;
    array.push(<ComponentToRender key = {index} id = {index}/>);
    this.setState=({
        componentList: array
    });
}

если это работает, это проблема с состоянием, содержащим ссылку на массив, которая не изменяется. Когда вы вызываете setState, даже если вы добавили его в массив, он по-прежнему видит ту же ссылку, потому что push не создает новый массив. Возможно, вы сможете использовать тот же массив, если вы также реализуете shouldComponentUpdate и проверите там длину массива нового состояния, чтобы увидеть, изменилось ли оно.

Ответ принят как подходящий

Это не то, как использовать реакцию. С ReactDOM.render() вы создаете совершенно новое дерево компонентов. Обычно вы делаете это только один раз для первоначального рендеринга вашего приложения. Все остальное будет отображаться функциями render() ваших компонентов. Если вы делаете это с ReactDOM.render(), вы в основном отбрасываете все, что уже было обработано, каждый раз, когда вы обновляете свои данные и воссоздаете их с нуля, тогда как на самом деле вам может потребоваться только добавить где-то один узел.

Также то, что вы фактически храните в состоянии компонента, должно быть простыми данными, а не компонентами. Затем используйте эти данные для рендеринга ваших компонентов в функции render().

Пример допустимого варианта использования:

class MyComponent extends Component{
        state = {
            periods: []
        };

        handleAddPeriod = () => {
            this.setState(oldState => ({
                periods: [
                    ...oldState.periods,
                    {/*new period data here*/}
                ],
            });
        };

        render() {
            return (
                <div id = "Wrapper">                                 
                    <button id = "addPeriod" onClick = {this.handleAddPeriod}>
                        Add Component
                    </button>
                    <div id = "container">
                        {periods.map((period, index) => (
                            <ComponentToRender id = {index} key = {index}>
                                {/* render period data here */}
                            </ComponentToRender>
                        ))}
                    </div>
                </div>
            );
        }
    }
}

Также вы не должны работать с глобальными переменными, как вы это делали с index. Если у вас есть данные, которые изменяются во время использования вашего приложения, это индикатор, который должен быть состоянием компонента.

Другие вопросы по теме