每当子组件呈现时,如何更改父组件的状态值?

时间:2020-09-16 12:50:39

标签: javascript reactjs

我正在学习React,我想弄清楚每当子组件呈现时如何更改父组件的状态。

这是我到目前为止所做的:

  1. 我传递了父母的state和setState并使用了useEffect,它可以产生无限的渲染。
  2. 我尝试在渲染之前调用该函数,该函数再次产生了无限的渲染。
  3. 我尝试使用forEach,但没有用。

这是一个代码框 https://codesandbox.io/s/modest-almeida-f9spo?file=/src/App.js

这是代码

<div class="container">
  <div class="a">
    <div class="child-a">Child of div a</div>
  </div>
  <div class="b">Div B</div>
</div>

.container {
  display: flex;
  justify-content: space-between;
}

.a,
.b {
  width: 49%;
}

.a {
  background: yellow;
}

.child-a {
  background: red;
}

.b {
  height: 200px;
  background: blue;
}

3 个答案:

答案 0 :(得分:0)

React确实不希望您具有双向数据流。但是,可以使用新的双向绑定帮助器: https://reactjs.org/docs/two-way-binding-helpers.html

但是请记住,由孩子引起的父项更改可以使父项重新呈现,这反过来又可以对孩子进行更改并导致无限循环。

您还可以签出Redux(https://redux.js.org/)之类的库,以拥有每个组件都可以访问和订阅事件的全局存储。

答案 1 :(得分:0)

您应该研究使用React Redux来管理这种行为。

但是,您可以将回调函数从Parent组件传递给Child组件。

示例:

class ChildComponent extends React.Component {

  constructor(props)
  {
    super(props);
  }

  componentDidMount()
  {
    props.onChildRendered();
  }

  render() {
    return (
      
    );
  }
}

class ParentComponent extends React.Component {

  constructor(props)
  {
    super(props);

    this.state = {
      childRendered = false;
    }
  }

  onChildRendered = () => {
    this.setState({
      childRendered: true
    });
  }

  render() {
    return (
      <ChildComponent onChildRendered={ this.onChildRendered }/>
    );
  }
}

在父组件中声明一个函数,只要该函数被触发,就可以更改其父状态。

然后将函数作为道具传递给子组件。

在安装子组件时,您将触发作为道具传递的函数。

这会触发父组件中的函数并更改其状态,从而导致重新渲染。

这绝不会导致无限循环,因为子组件中的componentDidMount()仅在组件的初始安装时被触发。


应谨慎使用此技术,因为有更好的方法来管理事物,例如使用状态管理中间件(例如Redux)。

可能 是可以接受的,但这仅仅是为了通知父母孩子已经渲染,但是这是惯例,并鼓励数据从父母那里流向父母。孩子们。

父级组件中所需的子级组件中的任何数据通常都移至父级。状态提升的过程称为“状态提升”。

答案 2 :(得分:0)

在父组件中计算totalPrice和折扣

尝试以下代码:

import React, { useState, useEffect } from "react";
import "./styles.css";
import data from "./data";

export default function App() {
  const [total, setTotal] = useState({
    price: 0,
    discount: 0
  });

  useEffect((prop) => {
    calcTotal();
  }, []);

  function calcTotal() {
    const newTotal = { ...total };
    data.forEach((item) => {
      newTotal.price += item.price;
      newTotal.discount += item.discount;
    });
    setTotal(newTotal);
  }

  return (
    <div className="App">
      <div>{JSON.stringify(data)}</div>
      <table>
        <thead>
          <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Price</th>
          </tr>
        </thead>
        <tbody>
          {data.map((item) => (
            <Item key={item.id} data={item} total={total} />
          ))}
        </tbody>
        <Total total={total} />
      </table>
    </div>
  );
}

function Item(props) {
  const item = props.data;
  return (
    <tr>
      <td>{item.id}</td>
      <td>{item.name}</td>
      <td>{item.price}</td>
    </tr>
  );
}

function Total(props) {
  const total = props.total;
  return (
    <tfoot>
      <tr>
        <th colSpan="2">Total Price: </th>
        <td>{total.price}</td>
      </tr>
      <tr>
        <th colSpan="2">Total Discount: </th>
        <td>{total.discount} </td>
      </tr>
    </tfoot>
  );
}