简体   繁体   English

从同级 React 组件中的表单提交刷新一个子 React 组件

[英]Refresh one child React component from form submit in sibling React component

I have a component called Bills, which embeds two child components, AddBill and DisplayBills.我有一个名为 Bills 的组件,它嵌入了两个子组件 AddBill 和 DisplayBills。

AddBill is a managed webform which submits the fields as json to an API endpoint (using fetch post). AddBill 是一个托管网络表单,它将字段作为 json 提交到 API 端点(使用 fetch post)。

DisplayBills gets Bill data as json from an API endpoint and displays this in an HTML table (using fetch). DisplayBills 从 API 端点以 json 形式获取账单数据,并将其显示在 HTML 表中(使用 fetch)。

When I click the submit button on the webform in AddBill, I would like to submit the data to the database via the API endpoint, and then I would like to do a refresh of DisplayBills to show this bill is now in the database.当我在 AddBill 中单击 webform 上的提交按钮时,我想通过 API 端点将数据提交到数据库,然后我想刷新 DisplayBills 以显示此帐单现在在数据库中。

I've tried several ways of wiring this up but nothing seems to work.我已经尝试了几种连接方式,但似乎没有任何效果。

The simplest way is to use a prop to inform the parent when a new bill is added, and add it to the bills state array which is passed into DisplayBills.最简单的方法是在添加新账单时使用 prop 通知父级,并将其添加到传入 DisplayBills 的 bills 状态数组中。

import React, { useState } from 'react';
import './styles.css';

function AddBill({ onAddBill }) {
  const [name, setName] = useState('');
  const [cost, setCost] = useState(0);

  function handleSubmit(e) {
    e.preventDefault();
    onAddBill({ name, cost });
    setName('');
    setCost(0);
  }

  return (
    <form className="add-bill" onSubmit={handleSubmit}>
      <input
        type="text"
        value={name}
        placeholder="Bill name"
        onChange={e => setName(e.target.value)}
      />
      <input
        type="number"
        min="0"
        value={String(cost)}
        placeholder="Cost"
        onChange={e => setCost(Number(e.target.value))}
      />
      <button type="submit">Add</button>
    </form>
  );
}

function DisplayBills({ bills }) {
  if (!bills.length) {
    return <div>No bills yet!</div>;
  }

  return (
    <div className="bill-list">
      {bills.map(bill => (
        <div key={bill.name}>
          Bill {bill.name} cost ${bill.cost}
        </div>
      ))}
    </div>
  );
}

function Bills() {
  const [bills, setBills] = useState([]);

  function handleAddBill(bill) {
    setBills([bill, ...bills]);
  }

  return (
    <div className="bills">
      <AddBill onAddBill={handleAddBill} />
      <DisplayBills bills={bills} />
    </div>
  );
}

export default function App() {
  return (
    <div className="App">
      <Bills />
    </div>
  );
}

Sandbox: https://codesandbox.io/s/agitated-pine-o5c7g沙盒: https : //codesandbox.io/s/agitated-pine-o5c7g

Note that I have used the bill name as the unique key, so really I should be enforcing that it is unique, or else just creating a unique ID for each bill (arrays should have unique IDs for rendering in React).请注意,我已经使用账单名称作为唯一键,所以我真的应该强制它是唯一的,或者只是为每个账单创建一个唯一的 ID(数组应该有唯一的 ID 以便在 React 中呈现)。

As per comments if you're using class components your state will look more like this:根据评论,如果您使用类组件,您的状态将更像这样:

class Bills extends PureComponent {
  state = { bills: [] }

  handleBillAdd = bill => {
    this.setState({ bills: [bill, ...this.state.bills] });
  }
}

When you call your handleAddBill AND API call is successful, in your state save something like this lastCall: Date.now() and pass that piece of state to DisplayBills component as props <DisplayBills lastCall={this.state.lastCall} /> .当您调用handleAddBill API 调用成功时,在您的state保存类似lastCall: Date.now()并将该状态作为props传递给 DisplayBills 组件<DisplayBills lastCall={this.state.lastCall} /> Now every time you call handleAddBill function, DisplayBills component's props will be updated with a unique value.现在每次调用handleAddBill函数时,DisplayBills 组件的props都会更新为唯一值。 In your DisplayBills component's componentDidUpdate(prevProps, prevState) life-cycle method, check if prevProps.lastCall !== this.props.lastCall , if they are different, then make your new API call to fetch latest bills, if they are same, that means handleAddBill is not called successfully so you don't have to update your DisplayBills component.在 DisplayBills 组件的componentDidUpdate(prevProps, prevState)生命周期方法中,检查是否prevProps.lastCall !== this.props.lastCall ,如果它们不同,则调用新的 API 来获取最新的账单,如果它们相同,这意味着handleAddBill未成功调用,因此您不必更新 DisplayBills 组件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM