Изменение массива в состоянии не отображается на странице

Я хочу иметь простой массив, который при нажатии кнопки перемешивает массив, а затем мгновенно отображает новый массив на странице.

Массив перемешивается, когда страница загружается и функция shuffle () успешно вызывается до завершения, когда я нажимаю кнопку Shuffle, но изменение никогда не отображается для пользователя. Я пробовал явно установить состояние и использовать this.setState (), и ни один из них не вызывает рендеринга изменения массива.

const Card = props => {
  return (
    <p>
      {props.title}: {props.text}
    </p>
  );
};

class Deck extends React.Component {
  constructor(props) {
    super(props);
    this.shuffle = this.shuffle.bind(this);
    this.state = {
      title: props.title,
      count: props.cards.length,
      cardsInDeck: props.cards
    };

    this.shuffle();
  }

  shuffle(e) {
    console.info("shuffling " + this.state.title + "...");

    let c = this.state.cardsInDeck.length;
    let shuffledArray = this.state.cardsInDeck;
    while (c > 0) {
      let index = Math.floor(Math.random() * c);
      c--;
      let temp = this.state.cardsInDeck[c];
      shuffledArray[c] = shuffledArray[index];
      shuffledArray[index] = temp;
    }

    //this.state.cardsInDeck = shuffledArray;
    this.setState({cardsInDeck: shuffledArray});

    console.info("done shuffling " + this.state.title + "...");
  };

  render() {
    return (
      <div>
        <div className = "card">
          <div className = "card-body">
            <h5 className = "card-title">{this.state.title} - {this.state.count} cards</h5>
            <button type = "button" className = "btn btn-info" onClick = {this.shuffle}>
              Shuffle
            </button>
          </div>
        </div>
        {this.state.cardsInDeck}
      </div>
    );
  }
}

var jobs = [
  { title: "job1", text: "30", return: "20" },
  { title: "job2", text: "40", return: "30" },
  { title: "job3", text: "50", return: "40" },
  { title: "job4", text: "50", return: "40" },
  { title: "job5", text: "50", return: "40" },
  { title: "job6", text: "50", return: "40" },
  { title: "job7", text: "60", return: "50" }
];

const jobItems = jobs.map(job => (
  <Card key = {job.title} title = {job.title} text = {job.text + " " + job.return} />
));

var workers = [
  { name: "worker1", cost: "30" },
  { name: "worker2", cost: "30" },
  { name: "worker3", cost: "30" },
  { name: "worker4", cost: "30" },
  { name: "worker5", cost: "30" },
  { name: "worker6", cost: "30" },
  { name: "worker7", cost: "30" }
];

const workerItems = workers.map(worker => (
  <Card key = {worker.name} title = {worker.name} text = {worker.cost} />
));

class App extends React.Component {
  render() {
    return (
      <div className = "row">
        <div className = "col">
          <Deck title = "Jobs" cards = {jobItems} />
        </div>
        <div className = "col">
          <Deck title = "Workers" cards = {workerItems} />
        </div>
      </div>
    );
  }
}

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

Codepen - ChildStackTest

Как я могу показать это изменение пользователю?

Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
0
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы изменяете состояние непосредственно в этих строках:

let shuffledArray = this.state.cardsInDeck;

shuffledArray[c] = shuffledArray[index];
shuffledArray[index] = temp;

Может быть источником проблемы ...

Когда я назначил shuffledArray как this.state.cardsInDeck, назначается ли он по ссылке? Значит, любые изменения, которые я вношу в shuffledArray, будут внесены в this.state.cardsInDeck? Я думал, что javascript всегда назначается объектом?

LCIII 24.07.2018 17:12

Прочтите эту статью ... в ней упоминается ваша проблема и дается несколько хороших решений для нее ... medium.freecodecamp.org/…

froston 24.07.2018 17:15

+1 А, значит, было все-таки присваивается по ссылке, поэтому любые изменения в [shuffledArray] также изменяли состояние, которое должно считаться неизменным. Это определенно источник моей проблемы. Спасибо!

LCIII 24.07.2018 17:26
Ответ принят как подходящий

Проблема не в рендеринге ваших компонентов, а в самом методе shuffle(). Проблема, кажется, здесь:

let shuffledArray = this.state.cardsInDeck;

Это создает переменную, которая содержит Справка для переменной состояния, а не локальную копию, над которой вы можете работать. Правильный способ сделать это:

let shuffledArray = this.state.cardsInDeck.slice();

Затем также измените эту строку:

let temp = this.state.cardsInDeck[c];

к:

let temp = shuffledArray[c];

и он должен работать.


Рабочая вилка: https://codepen.io/anon/pen/xJdNQO?editors=0011

Это сработало. Использование slice () для создания копии, а не ссылки - очень творческий подход. Спасибо!

LCIII 24.07.2018 17:27

Рад, что помог. Если вам нравится ES6, вы также можете скопировать с помощью [...this.state.cardsInDeck], если предпочитаете этот синтаксис.

Chris 24.07.2018 17:28

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