Повторное отображение детей по щелчку мыши не работает

#javascript #reactjs

Вопрос:

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

К сожалению, моя кнопка «Обновить сетку» работает не так, как предполагалось. Даже при нажатии на кнопки, которые были нажаты ранее, остаются активированными (т. е. их цвет оранжевый). Когда я сбрасываю состояние своей сетки при вызове setGrid() , я не уверен, где я ошибаюсь.

Мы очень ценим вашу помощь. Поскольку я совершенно новичок в самой реакции, некоторые рекомендации о лучших практиках и т. Д. было бы также очень полезно!

Заранее спасибо.

Код:

 import ReactDOM from 'react-dom';
import './index.css';

class Box extends React.Component {
  constructor() {
    super();
    this.state = {
      color: 'white',
      activated: false
    }
  }

  initiate() {
    this.setState({color: 'white', activated:false})
  }

  componentDidMount() {
    this.initiate()
  }

  click() {
    if(!this.state.activated) {
      this.setState({color: 'orange', activated: true})
    }
    else {
      this.setState({color: 'white', activated: false})
    }
  }

  render() {
    return <div className="box" style={{ backgroundColor: this.state.color }} onClick={() => this.click()}/>
  }
} 

class Grid extends React.Component {
  constructor() {
    super();
    this.state = {grid: []}
  }

  componentDidMount() {
    this.setGrid()
  }

  setGrid() {
    let grid = [];
    for (let row = 0; row < 20; row  ) {
      for (let col = 0; col < 20; col  ) {
        grid.push(<Box />)
      }
    }
    this.setState({grid: grid})
  }

  render() {
    return (
      <>
        <div className="grid">{this.state.grid}</div>
        <button onClick={() => this.setGrid()}>Refresh Grid</button>
      </>
      )
  }
}

ReactDOM.render(
  <Grid />,
  document.getElementById('root')
);
 

Ответ №1:

Вы не назначаете ключ React элементам/компонентам, отображаемым в массиве, поэтому используется их относительный индекс, и, поскольку это не меняется от отрисовки к отрисовке, React отменяет повторный просмотр.

  1. Вы можете назначить уникальные ключи каждому Box компоненту, когда они будут созданы в grid состоянии. Вот пример использования генератора GUID от uuid .
     import { v4 as uuidV4 } from 'uuid';
    
    ...
    
    setGrid() {
      let grid = [];
      for (let row = 0; row < 5; row  ) {
        for (let col = 0; col < 5; col  ) {
          grid.push(<Box key={uuidV4()} />); // <-- add key
        }
      }
      this.setState({ grid: grid });
    }
     

Редактирование повторной визуализации детей по щелчку мыши не работает

  1. Вы можете использовать одну клавишу для div рендеринга grid . Сбросьте это значение при настройке/сбросе сетки.
     import { v4 as uuidV4 } from 'uuid';
    
    ...
    
    class Grid extends React.Component {
      constructor() {
        super();
        this.state = {
          grid: [],
          key: uuidV4()
        };
      }
    
      componentDidMount() {
        this.setGrid();
      }
    
      setGrid() {
        const grid = [];
        for (let row = 0; row < 5; row  ) {
          for (let col = 0; col < 5; col  ) {
            grid.push(<Box />);
          }
        }
        this.setState({
          grid,
          key: uuidV4() // <-- set/reset key
        });
      }
    
      render() {
        return (
          <>
            <div
              key={this.state.key} // <-- add key
              className="grid"
            >
              {this.state.grid}
            </div>
            <button onClick={() => this.setGrid()}>Refresh Grid</button>
          </>
        );
      }
    }
     

    Редактирование повторной визуализации детей по щелчку мыши не работает (раздвоение)

Ответ №2:

Очистите существующую сетку и установите новую сетку

   setGrid() {
    this.setState({ grid: [] }, () => {
      let grid = [];
      for (let row = 0; row < 20; row  ) {
        for (let col = 0; col < 20; col  ) {
          grid.push(<Box />);
        }
      }
      this.setState({ grid: grid });
    });
  }