Функциональный компонент React не выполняет рендеринг при изменении реквизита, переданного как массив

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

https://codesandbox.io/s/5ym4vkrnnk

или

import React, { PureComponent, Fragment } from "react";
import ReactDOM from "react-dom";

const SomeFunctionalComponent = props => {
  return <span>{props.array[0]}</span>;
};

class App extends PureComponent {
  state = {
    array: [1, 2, 3]
  };
  increase = () => {
    var array = this.state.array;
    array[0] = array[0] + 1;
    this.setState({ array: array });
    console.info(this.state.array);
  };
  render() {
    return (
      <Fragment>
        <button onClick = {this.increase}>Increase</button>
        <SomeFunctionalComponent array = {this.state.array} />
      </Fragment>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Мои вопросы:

  1. Почему это так?
  2. Как я могу это изменить?

Спасибо за любую помощь заранее!

Вы меняете значение в массиве, но ссылка на массив остается прежней. Поскольку react видит одну и ту же ссылку на объект до и после вызова increase(), он фактически не знает, что что-то изменилось. Вы должны попробовать использовать чистые функции и неизменяемость.

Fonzy 20.09.2018 17:51
Поведение ключевого слова "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) для оценки ваших знаний,...
1
1
1 076
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Никогда не изменяйте состояние напрямую

вы изменяете состояние прямо в коде, поэтому изменения не отражаются. Массив становится ссылкой на this.state.array, что вызывает нежелательную мутацию.

import React, { PureComponent, Fragment } from "react";
import ReactDOM from "react-dom";

const SomeFunctionalComponent = props => {
  return <span>{props.array[0]}</span>;
};

class App extends PureComponent {
  state = {
    array: [1, 2, 3]
  };
  increase = () => {
    var array = [...this.state.array];
    array[0] = array[0] + 1;
    this.setState({ array: array });
    console.info(this.state.array);
  };
  render() {
    return (
      <Fragment>
        <button onClick = {this.increase}>Increase</button>
        <SomeFunctionalComponent array = {this.state.array} />
      </Fragment>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

можно добавить, что array становится ссылкой на this.state.array, что вызывает нежелательную мутацию

Velimir Tchatchevsky 20.09.2018 17:43

Большое спасибо, похоже, мне не хватает некоторых базовых знаний о javascript ... Я подумал, когда напишу: var array = this.state.array; массив [0] = массив [0] + 1; Я копирую значение этого .state.array в другую переменную, а затем меняю его вместо того, чтобы изменять ссылку?

Tim von Känel 20.09.2018 17:43

Кстати, синтаксис распространения создает неглубокую копию. С этим простым кодом все в порядке, но если вы измените вложенное свойство нового массива, вы измените исходное.

devserkan 20.09.2018 17:45

@ TimvonKänel: вы используете тот же массив для внесения изменений, необходимых для создания полностью нового массива перед его изменением.

aravind_reddy 20.09.2018 17:46

@VelimirTchatchevsky спасибо, я добавил это в ответ

aravind_reddy 20.09.2018 17:47

@ TimvonKänel, прямое присвоение создает объект (массивы - это объекты), указывающий на одну и ту же ссылку на объект. Если вы измените свойство на новое, вы измените старое. Распространенный синтаксис, и Object.assign создает неглубокие копии, то есть они копируют только на один уровень в глубину. Итак, если вы измените вложенное свойство, вы измените старое.

devserkan 20.09.2018 18:04

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