如何在React中从父组件调用子组件的方法

时间:2020-04-21 20:03:06

标签: javascript reactjs

我有一个3 * 3正方形的网格。

单击正方形时,我们将背景颜色更改为绿色。

因此,我尝试将所有状态放入父级GridContainer中。

__restrict__

这将保存被单击的索引。

state = { gridCells: [] }; 嵌套GridContainer,网格嵌套Grid

Square

这是我当前的实现方式。

现在如何在重置点击时清除背景单元格并使背景再次变回白色?

render() {
    return (
      <div>
        <Grid action={this.handler} />    
        <button>Reset Clicks</button>
      </div>
    );
  }

因此,当我单击function Square(props) { const liClickHandler = event => { event.target.classList.add("highlight"); props.clickAction(); }; return <li onClick={e => liClickHandler(e)} />; } function Grid(props) { const gridHandler = index => { props.action(index); }; return ( <ul> {Array.from(new Array(9)).map((item, index) => ( <Square key={index} clickAction={() => gridHandler(index)} /> ))} </ul> ); } class GridContainer extends React.Component { state = { gridCells: [] }; handler = index => { let temp = [...this.state.gridCells]; temp.push(index + 1); this.setState({ gridCells: temp }); }; render() { return ( <div> <Grid action={this.handler} /> <button>Reset Clicks</button> </div> ); } } 时,它会调用方法Sqaure并调用clickAction

更新状态,我们有一个数组,按顺序单击了索引。

如何实现handler?我如何让我的孩子知道。

我维护状态错误吗?

沙盒链接:https://codesandbox.io/s/3-x-3-grids-s0b43?file=/src/index.js:640-1563

2 个答案:

答案 0 :(得分:2)

我建议您重新考虑组件的结构方式。

每个组件应该是具有自己的逻辑和状态的独立单元(当然,如果需要的话)。我说的是如果需要状态,因为理想情况下组件应该是无状态的。

Square类存在几个问题:

  1. 它通过event.target添加类,这是没有反应的方式。 React与虚拟DOM一起使用,并且拥有自己的与html交互的方法集。直接使用DOM-从以后为您的代码编写测试开始,会给您带来麻烦。
  2. 它不包含传入的信息,无论是否突出显示

这两个问题实际上导致您无法轻松重置正方形的显示。

我已经更新了您的示例:https://codesandbox.io/s/3-x-3-grids-uflhr?file=/src/index.js

它仍然不是理想的,但是您会注意到gridCells是通过props从顶部传递的。然后每个广场都有自己的道具参数。这允许状态通过流,并让正方形使用更新的类重新渲染。

答案 1 :(得分:1)

在做出反应时,您应该想到“反应”方式:

  • 通过道具传递必要的状态
  • 传递回调,以便孩子可以更新父状态

这里是演示的corrected version

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";
function Square(props) {
  return (
    <li onClick={props.onClick} className={props.active ? "highlight" : ""} />
  );
}

function Grid(props) {
  let squares = [];

  for (let i = 0; i < 9; i++) {
    squares.push(
      <Square
        key={i}
        onClick={() => props.onCellClick(i)}
        active={props.cells[i]}
      />
    );
  }

  return <ul>{squares}</ul>;
}

class GridContainer extends React.Component {
  state = {
    gridCells: []
  };

  onCellClick = index => {
    this.setState(prevState => {
      const newCells = [...prevState.gridCells];
      newCells[index] = true;
      return {
        gridCells: newCells
      };
    });
  };

  render() {
    return (
      <div>
        <Grid cells={this.state.gridCells} onCellClick={this.onCellClick} />

        <button
          onClick={() => {
            let that = this; //we could bind the callback aswell
            that.setState(() => ({ gridCells: [] }));
          }}
        >
          Reset Clicks
        </button>
      </div>
    );
  }
}

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