![](/img/trans.png)
[英]Selecting elements from a particular component which is rendered mulitple times in react
[英]Collect Data from the same component which is being rendered multiple times into an array to be sent to the server
我有一个创建页面,我要求用户一次又一次地填写同一个表单,用户想要的次数不限,一旦用户认为他们完成了填写表单,他们就可以点击提交按钮和所有数据在表单中将被发送到服务器。
我尝试在父组件上创建一个方法,并从同一个表单组件收集数据并将其发送回父组件。 但是我无法区分哪个表单正在发送数据。 如果用户在第一个表单中添加数据后进行了一些更改,然后再添加 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组件,容器是父组件。 希望所有这些都提供了足够的背景。
蒂亚!!
一种方法:
这是一个简单的例子( 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);
每次有人开始在任何字段中输入时,我如何处理添加卡片的另一个问题?
见https://codesandbox.io/s/vvm4lj3nqy
dirty: false
dirty: true
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();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.