从多次渲染的同一组件收集数据到数组中以发送到服务器

2024-01-07

我有一个创建页面,我要求用户一次又一次地填写相同的表单,次数不限,一旦用户认为他们已完成填写表单,他们可以单击提交按钮和所有数据表单中的内容将被发送到服务器。

我尝试在父组件上创建一个方法,并从同一表单组件收集数据并将其发送回父组件。但我无法区分哪个表单正在发送数据。如果用户在第一个表单中添加数据后进行了一些更改,然后再添加 3 个表单并填写它们,然后返回并对第一个表单进行更改,然后再将多个表单数据发送到服务器。

import React, { Component } from 'react'
import { connect } from 'react-redux'
import BeneficiaryFilter from 
'../../Commons/Filter/Beneficiary/BeneficiaryFilter'
import './style.scss'
import IndividualVendor from './IndividualVendor/InvidualVendor'
import Select from 'react-select'

// import actions to get data
import { fetchCompanyConfiguration } from 
'../../../../redux/vendor_payments/dashboard/actions/newPayTicket'

class Beneficiary extends Component {
  constructor (props) {
    super(props)
    this.state = {
      vendorTotalAmount: 0,
      vendorTotalCount: 1,
      dataToBeSent: []
    }
  }

  /**
   *
   * Check for click event on name change , increase number of 
   *   vendor by one, nut just once.
   */
  vendorAdd = () => {
    this.setState({
      vendorTotalCount: this.state.vendorTotalCount + 1
    })
  }

  /**
    * @param {amount}, change the state value for total for the 
individual ticket and then send the amount to component that shows 
the total amount.
   */
  onVendorAmountChange = amount => {
    this.setState({
      vendorTotalAmount: amount
    })
  }

  componentDidMount () {
    this.props.dispatch(fetchCompanyConfiguration())
  }

  addVendorDetails = data => {
    let dataToBeSent = {...this.state.dataToBeSent}
    dataToBeSent[`Vendor${Date.now()}`] = data
    this.setState({
      dataToBeSent
    })
  }

  render () {
    const { newPayTicket } = this.props
    const { vendorTotalCount, vendorTotalAmount } = this.state
    let listOfVendors = [];
    for (let i = 1; i <= vendorTotalCount; i++) {
      listOfVendors.push(
        <IndividualVendor
          key={i}
          vendorAdd={this.vendorAdd}
          onVendorAmountChange={this.onVendorAmountChange}
          newPayTicket={newPayTicket}
          addVendorDetails={this.addVendorDetails}
          count={vendorTotalCount}
        />
      )
    }
    return (  
      <div className='beneficiary-container'>
        <BeneficiaryFilter
          vendorTotalCount={this.state.vendorTotalCount}
          vendorTotalAmount={this.state.vendorTotalAmount}
        />
        <div className='main-container'>
          <div className='add-beneficiary-container'>
            {listOfVendors}
          </div>
        </div>
      </div>
    )
  }
}

const mapStateToProps = state => {
  return {
    newPayTicket: state.newPayTicket.configurationData
  }
}
export default connect(mapStateToProps)(Beneficiary)

上面是父组件,我想从每个组件添加数据。单个组件具有

State for the form, 
class Vendor extends Component {
  constructor (props) {
    super(props)
    this.state = {
      venodrName: '',
      vendorId: '',
      vendorAuthType: true,
      vendorAccountId: '',
      vendorAccountName: '',
      selectedBankAccountIfsc: '',
      selectedBankAccountNumber: '',
      unauthorisedBankAccountName: '',
      unAuthselectedBankAccountNumber: '',
      unAuthselectedBankAccountIfsc: '',
      vendorNarration: '',
      vendorCategoryId: '',
      vendorCostCenterId: '',
      vendorDepartmentId: '',
      vendorAmount: '',
      vendorTds: '',
      vendorGstDropdown: '',
      vendorGst: '',
      vendorDetails: {},
      errors: {}
    }
  }

individualVendor 组件只不过是一个具有可填充字段的表单,每次有人从当前表单切换到下一个表单时,我希望将该字段中的所有数据添加到父组件的数组中,并且一旦用户完成,他们可以单击提交并发送父组件中 dataToBeSent[] 中收集的所有数据。

我不确定如何从多次渲染的同一组件中获取数据并将数据存储在父组件的对象中,而且如何确保即使相同的表单也仅存储表单数据一次正在被一次又一次地改变。

例如:如果我开始在 individualVendor 组件的第一个实例中添加信息,然后转到同一 individualVendor 组件的下一个实例,我想确保父组件中的数组只有 2 个对象,而不是新对象任何时候编辑/更改表单。下面我添加了页面设计的模型,每个行项只是 individualVendor 组件,容器是父组件。希望这一切提供了足够的背景。

TIA!!

页面的样机设计 https://i.stack.imgur.com/3E0Yg.png


一种方法是:

  1. 将状态提升到父组件,这意味着您的表单组件没有任何状态,仅从 props 接收数据并渲染它。父组件负责存储和更新数据。
  2. 给每个表单数据一个唯一的id,以便于查找和更新。

这是一个简单的例子(https://codesandbox.io/s/5v389j6vp4 https://codesandbox.io/s/5v389j6vp4):

import React, { Component } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class Vendor extends Component {
  render() {
    const {
      vendorName,
      vendorNarration,
      vendorAmount,
      onChangeName,
      onChangeNarration,
      onChangeAmount
    } = this.props;

    return (
      <form onSubmit={e => e.preventDefault()}>
        Name : <input value={vendorName} onChange={onChangeName} /> <br />
        Narration :{" "}
        <input value={vendorNarration} onChange={onChangeNarration} /> <br />
        Amount : <input value={vendorAmount} onChange={onChangeAmount} /> <br />
        <hr />
      </form>
    );
  }
}

const DEFAULT_DATA = {
  vendorName: "",
  vendorNarration: "",
  vendorAmount: ""
};
class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      dataToBeSent: []
    };
  }

  addVendor() {
    this.setState(state => ({
      dataToBeSent: state.dataToBeSent.concat({
        id: Date.now(),
        ...DEFAULT_DATA
      })
    }));
  }

  handleOnChangeName(e, id) {
    const newData = this.state.dataToBeSent.map(data => {
      if (data.id !== id) {
        return data;
      }

      return {
        ...data,
        vendorName: e.target.value
      };
    });

    this.setState({ dataToBeSent: newData });
  }

  handleOnChangeNarration(e, id) {
    const newData = this.state.dataToBeSent.map(data => {
      if (data.id !== id) {
        return data;
      }

      return {
        ...data,
        vendorNarration: e.target.value
      };
    });

    this.setState({ dataToBeSent: newData });
  }

  handleOnChangeAmount(e, id) {
    const newData = this.state.dataToBeSent.map(data => {
      if (data.id !== id) {
        return data;
      }

      return {
        ...data,
        vendorAmount: e.target.value
      };
    });

    this.setState({ dataToBeSent: newData });
  }

  renderForms() {
    const { dataToBeSent } = this.state;

    return dataToBeSent.map(data => (
      <Vendor
        key={data.id}
        {...data}
        onChangeName={e => this.handleOnChangeName(e, data.id)}
        onChangeNarration={e => this.handleOnChangeNarration(e, data.id)}
        onChangeAmount={e => this.handleOnChangeAmount(e, data.id)}
      />
    ));
  }

  render() {
    return (
      <div className="App">
        <button onClick={this.addVendor.bind(this)}>Add Vendor</button>
        {this.renderForms()}
        <hr />
        <h4>Result</h4>
        <div>{JSON.stringify(this.state.dataToBeSent, null, 2)}</div>
      </div>
    );
  }
}

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

Edit

我该如何处理每次添加卡的另一个问题 有人开始在任何字段中输入内容?

see https://codesandbox.io/s/vvm4lj3nqy https://codesandbox.io/s/vvm4lj3nqy

  1. 添加一个布尔值dirty: false对每个表单数据
  2. 在每个输入更改集上dirty: true
  3. in componentDidUpdate检查是否至少有一个表格dirty: false,如果没有添加。

像这样

  componentDidUpdate(prevProps, prevState) {
    if (prevState.dataToBeSent !== this.state.dataToBeSent) {
      const clean = this.state.dataToBeSent.find(data => !data.dirty);

      if (!clean) {
        // Add clean form
        this.addVendor();
      }
    }
  }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从多次渲染的同一组件收集数据到数组中以发送到服务器 的相关文章

随机推荐

  • C++11 递归可变参数模板

    我想了解递归可变参数模板是如何工作的 include
  • Java 中的“快速”整数幂

    简短回答 糟糕的基准测试方法 你可能认为我现在已经明白了 该问题被表述为 找到一种快速计算x y的方法 其中x和y是正整数 典型的 快速 算法如下所示 public long fastPower int x int y Replaced m
  • 并发修改异常[重复]

    这个问题在这里已经有答案了 我有一小段代码 它给了我并发修改异常 我无法理解为什么我不断收到它 即使我没有看到任何并发修改正在进行 import java util public class SomeClass public static
  • SQL Server 和 Firebase/PouchDB 同步

    我正在构建一个 Web 应用程序 客户端需要在离线状态下通过浏览器访问数据存储 我正在考虑使用 Firebase 或 PouchDB 数据库在应用程序内实现此目的 但是 对于后端 我使用 SQL Server 我可以将 Firebase P
  • HTML 或 CSS 中的“父级”是什么?

    我被介绍到以下代码 div Here is span a span element span which is blue as span elements are set to be div div class extra style co
  • 如何在打字稿中将 array.map 与元组一起使用?

    每当我使用array map对于元组 Typescript 将其推断为通用数组 例如 以下是简单 3x3 数独游戏的一些片段 const a Blank type Blank typeof type Cell number Blank ty
  • 当扩展复杂类型时混合继承吗?

    我的架构中有以下内容
  • 迭代日期范围(scala 方式)

    给定开始日期和结束日期 我想使用 foreach map 或类似函数按天迭代它 就像是 DateTime now to DateTime now 5 day by 1 day foreach println 我在用https github
  • 放置新的零会占用内存吗?

    我有以下代码 struct foo void bar foo d new d foo d 是否表达new d foo d 留下指向的对象d不变 更具体地说 如果类foo并且其中递归包含的所有对象都只有简单的复制构造函数 那么new d fo
  • SQL 条件求和

    我目前有一个大型 SQL 语句 我将以下行添加到其中 以便获取每个交易 ID 的总现金 这是唯一的 select sum cash from Table a where a branch p branch and a transID p t
  • 视频流和 Android

    今天 对于我的一个应用程序 Android 2 1 我想从 URL 流式传输视频 就我探索的 Android SDK 而言 它非常好 我很喜欢almost它的每一个部分 但现在谈到视频流 我有点迷失了 如果您需要有关 Android SDK
  • Java 将 JFrame 附加到正在运行的应用程序窗口?

    如何将右上角的 JFrame 连接到另一个应用程序打开的窗口并在调整大小时保持不变 是否可以 这是我想要完成的任务的图表 谢谢您的帮助 如果这不可能 有其他选择吗 获取窗口大小 位置并相应设置我自己的 jframe 的方法 您要求 Java
  • 在具有不同 x-y 轴的面中绘制多个矩阵

    我从一组在线论坛收集了数据 并想使用 ggplot 和facets 每个论坛一个facet 绘制代表用户 A 回复用户 B 次数的矩阵 这是加载玩具示例的代码 library ggplot2 library dplyr df edges l
  • 互斥量在繁忙时被破坏

    EventHandler类有一个单例对象来接收来自主线程的事件 它将输入注册到向量 并创建一个运行 lambda 函数的线程 该函数在从向量中删除输入之前等待一段时间 以防止在一段时间内重复执行该输入的事件 但我在繁忙错误时遇到互斥体被破坏
  • 使用 MATLAB 进行数字图像处理,使用 3 种技术

    我有 MATLAB 作业 我必须使用 3 种图像处理技术 所以我应该制定一个任务 然后使用 3 种技术来解决它 例如 阈值处理 分割 形态学 恢复 直方图均衡 噪声消除 我需要一些想法以及如何解决它 你能帮助我吗 谢谢 版本中 我在某本书中
  • wsdl 中的“any”是什么以及如何使用 php 调用 wsdl 函数?

    这段代码是我的 wsdl 的一小部分 这里我没看懂
  • Pandas - 计算和旋转以获得前两年的收入

    我有一个如下所示的数据框 df pd DataFrame stud id 101 101 101 101 101 102 102 102 sub code CSE01 CSE01 CSE01 CSE01 CSE02 CSE02 CSE02
  • Ansible 剧本,在提升模式下使用特定(域)用户运行 powershell 脚本的正确语法是什么?

    在离线环境中运行 Ansible 2 4 2 使用 kerberos 进行身份验证 通过 ansible playbook 在提升模式下使用特定 域 用户 DOMAIN someuser 运行 powershell 脚本的正确语法是什么 我
  • 如何使用 HtmlUnit 搜索 YouTube

    我想知道 YouTube 是否可以搜索HtmlUnit http htmlunit sourceforge net 我开始写代码 如下 import java io IOException import java net Malformed
  • 从多次渲染的同一组件收集数据到数组中以发送到服务器

    我有一个创建页面 我要求用户一次又一次地填写相同的表单 次数不限 一旦用户认为他们已完成填写表单 他们可以单击提交按钮和所有数据表单中的内容将被发送到服务器 我尝试在父组件上创建一个方法 并从同一表单组件收集数据并将其发送回父组件 但我无法