React应用未按预期对更改做出反应。为什么?

时间:2019-04-08 11:54:29

标签: javascript reactjs

人。我可能有一个菜鸟问题,不过我还是会射击。下面的代码段非常简单,我不应该遇到问题,但是我们开始吧。我正在尝试获取ColorsGrid组件中的颜色列表。简而言之,当用户通过下拉列表更改难度级别时,应生成一组新的颜色并进行显示。我认为这是一个非常简单的练习,但是事情并未按预期进行。每当我改变难度时,它都不会做出反应(重新呈现ColorsGrid组件),只有在我再次选择另一个(困难)级别之后,上一个才会引发重新呈现。例如,如果要在初始渲染后选择“中”(默认级别设置为“简单”),则没有任何变化。但是,如果我回到“轻松”(或选择其他任何难度),那么是否会发生与前一个(中等难度)相对应的更改,即ColorsGrid重新渲染,因此显示了与中等难度相对应的网格。我在做什么错了?

下面是相关代码。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

// Get random rgb color
function randomColor() {
  let r = Math.floor(Math.random() * 256);
  let g = Math.floor(Math.random() * 256);
  let b = Math.floor(Math.random() * 256);

  return `rgb(${r}, ${g}, ${b})`;
}

// Set length of color list array as a funciton of difficulty 
function colorsListLength(difficulty) {
  switch (true) {
    case difficulty === 'expert':
      return 25;
    case difficulty === 'hard':
      return 20;
    case difficulty === 'medium':
      return 10;
    default:
      return 5;
  }
}

// Get color list array
function colorsList(colorsLength = 5) {
  const colors = [];

  while (colors.length < colorsLength) {
    colors.push(randomColor());
  }

  return colors;
}

// Set random color to guess from (above) color list array
function randomColorToGuess(colors) {
  const index = Math.floor(Math.random() * colors.length);

  return colors[index];
}

// Set number of game tries as a function of difficulty
function numberOfTries(difficulty) {
  switch (true) {
    case difficulty === 'expert' || difficulty == 'hard':
      return 2;
    case difficulty === 'medium':
      return 1;
    default:
      return 0;
  }
}

// Colors grid component
function ColorsGrid({ difficulty, colorsList }) {
  return (
    <div>
      <strong>Colors Grid</strong>
      <p>Difficulty: {difficulty}</p>
      <div>
        {colorsList.length > 0 ? (
          colorsList.map(color => (
            <div
              style={{
                backgroundColor: color,
                height: '3rem',
                width: '3rem',
                borderRadius: '50%',
              }}
              key={color}
            />
          ))
        ) : (
          <div>Loading colors...</div>
        )}
      </div>
    </div>
  );
}

// Main component
class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      difficulty: 'easy',
      colorsList: [],
    };

    this.colorsArray = this.colorsArray.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  componentDidMount() {
    this.colorsArray(this.state.difficulty);
  }

  colorsArray() {
    const colors = colorsList(colorsListLength(this.state.difficulty));
    const colorToGuess = randomColorToGuess(colors);

    this.setState(() => ({
      colorsList: colors,
      gameTries: numberOfTries(this.state.difficulty),
      colorToGuess,
    }));
  }

  handleChange(e) {
    this.setState({
      difficulty: e.target.value,
    });

    this.colorsArray(this.state.difficulty); // I was under the impression the (difficulty) state had already been updated here
  }

  render() {
    return (
      <div className="App">
        <h1>Colors</h1>
        <div style={{ textAlign: 'right' }}>
          <select
            id="difficulty"
            value={this.state.difficulty}
            onChange={this.handleChange}
          >
            <option value="easy">Easy</option>
            <option value="medium">Medium</option>
            <option value="hard">Hard</option>
            <option value="expert">Expert</option>
          </select>
        </div>
        <ColorsGrid
          colorsList={this.state.colorsList}
          difficulty={this.state.difficulty}
        />
      </div>
    );
  }
}

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

2 个答案:

答案 0 :(得分:3)

这是因为setState()异步

  

setState(newState,回调);

为了获得刚刚选择的难度,您必须像这样更改代码:

this.setState({
  difficulty: e.target.value,
 }, () => this.colorsArray(this.state.difficulty)
);

答案 1 :(得分:-1)

问题在于您对setState的调用是否协调。以下是解决问题的方法:

  colorsArray(difficulty) {
    const colors = colorsList(colorsListLength(difficulty));
    const colorToGuess = randomColorToGuess(colors);

    this.setState(() => ({
      difficulty,
      colorsList: colors,
      gameTries: numberOfTries(this.state.difficulty),
      colorToGuess
    }));
  }

  handleChange(e) {
    this.colorsArray(e.target.value);
  }

您可以看到事件处理程序对颜色更新功能进行了一次调用。然后计算出新的颜色并将状态设置在一个位置。