首页 > 解决方案 > 单击时重新渲染子项不起作用

问题描述

我目前正在学习 React,并正在尝试编写一个可编程网格,其中的框在单击时会改变颜色。

不幸的是,我的“刷新网格”按钮没有按预期工作。即使单击之前被单击的框仍保持激活状态(即它们的颜色为橙色)。当我在调用时重置我的网格状态时,setGrid()我不确定我在哪里弄错了。

非常感谢您的帮助。由于我对 React 本身完全陌生,因此一些关于最佳实践等的建议也会有很大帮助!

提前致谢。

代码:

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')
);

标签: javascriptreactjs

解决方案


您没有为数组中呈现的元素/组件分配 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>
          </>
        );
      }
    }
    

    编辑 re-rendering-of-children-on-click-doesnt-work (forked)


推荐阅读