React - 需要一些帮助来将数据保存到 table
React - require some aid with saving data to a table
我有一个 table 具有动态生成的列 headers 和行,用户可以在行中输入数据,当他们单击“保存”时,数据应保存到该行中,但在此刻它没有将值保存到 table 但它正在将它们保存在我的数据库中。理想情况下,我希望这样,当单击保存按钮时,数据将保存到该行,然后可以在该行中查看(如果这有意义的话)。
这是我正在使用的代码(我知道它现在一团糟!):
数据输入表单代码:
import React from 'react';
import AppStore from '../../stores/AppStore';
export default class RowForm extends React.Component {
state = {dataEntries: []};
onChange = (event, element) => {
let dataEntries = this.state.dataEntries;
dataEntries[element] = event.target.value;
this.setState({dataEntries});
};
editStop = () => {
this.props.editStop();
};
handleSubmit = (e) => {
e.preventDefault();
let access_token = AppStore.getToken();
let id = AppStore.getTable().id;
let dataEntries = this.state.dataEntries;
let dataEntriesArray = [];
for (let key in dataEntries) {
if (dataEntries.hasOwnProperty(key)) {
dataEntriesArray.push({contents: dataEntries[key]});
}
}
this.props.handleSubmit(access_token, id, dataEntriesArray);
};
componentDidMount() {
let nameArray = AppStore.getTable().columns.map((obj) => {
return obj.name;
});
let dataEntries = nameArray.reduce((obj, name) => {
obj[name] = null;
return obj;
}, {});
this.setState({dataEntries});
}
render() {
let {dataEntries} = this.state;
return (
<tr>
{Object.keys(dataEntries).map((element) => {
return (
<td key={element}><input type="text" className="form-control" id={element} placeholder="enter data" value={dataEntries[element]} onChange={event => this.onChange(event, element)} /></td>
);
})}
<td>
<button className="btn btn-default" onClick={this.editStop}><i className="fa fa-ban"></i>Cancel</button>
<button className="btn btn-success" onClick={this.handleSubmit}><i className="fa fa-check"></i>Save</button>
</td>
</tr>
);
}
数据输入并提交后(是一个objects的数组,如dataEntriesArray = [{contents: "value"}, {contents: "value"}, {contents : "value"}, {内容: "value"}].
这是我渲染 table 的方式(我认为这就是问题所在):
import React from 'react';
import TableHeader from './TableHeader.jsx';
import RowForm from './RowForm.jsx';
import {createRow} from '../../actions/DALIActions';
import AppStore from '../../stores/AppStore';
export default class Table extends React.Component {
state = {rows: [], isNew: false, isEditing: false};
handleAddRowClickEvent = () => {
let rows = this.state.rows;
rows.push({isNew: true});
this.setState({rows: rows, isEditing: false});
};
handleEdit = (row) => {
this.setState({isEditing: true});
};
editStop = () => {
this.setState({isEditing: false});
};
handleSubmit = (access_token, id, dataEntriesArray) => {
createRow(access_token, id, dataEntriesArray);
};
render() {
let {rows, isNew, isEditing} = this.state;
let headerArray = AppStore.getTable().columns;
return (
<div>
<div className="row" id="table-row">
<table className="table table-striped">
<thead>
<TableHeader />
</thead>
<tbody>
{rows.map((row, index) => this.state.isEditing ?
<RowForm formKey={index} key={index} editStop={this.editStop} handleSubmit={this.handleSubmit} /> :
<tr key={index}>
{headerArray.map((element, index) => {
return (
<td key={index} id={element.id}></td>
);
})}
<td>
<button className="btn btn-primary" onClick={this.handleEdit.bind(this, row)}><i className="fa fa-pencil"></i>Edit</button>
</td>
</tr>)}
</tbody>
</table>
</div>
<div className="row">
<div className="col-xs-12 de-button">
<button type="button" className="btn btn-success" onClick={this.handleAddRowClickEvent}>Add Row</button>
</div>
</div>
</div>
);
}
}
我目前正在使用 flux,并且理想情况下希望暂时继续使用它(我知道 redux,但理想情况下我希望在开始重构我的代码之前让它在 flux 中工作)。我怀疑我渲染 table.
的方式有问题
非常感谢任何帮助,尤其是示例!
谢谢你的时间!
看起来您可能想将 table 数据提取到您的商店中,您的 UI 子元素触发更改事件,然后您的商店更新其数据并触发更改事件,您的父组件可以监听和更新。
类似于下面的简化示例,它改变了数组元素:
class Store extends EventEmitter {
constructor() {
super()
this.data = [ 'a', 'b', 'c' ]
}
onChange() {
this.emit( 'update', this.data )
}
mutate( index, value ) {
this.data[ index ] = value
this.onChange()
}
}
var store = new Store()
class ChildComponent extends React.Component {
constructor( props ) {
super( props )
}
// You probably want to use a dispatcher rather than directly accessing the store
onClick = event => {
store.mutate( this.props.index, this.props.value + 'Z' )
}
render() {
return <button onClick={ this.onClick }>{ this.props.value }</button>
}
}
class ParentComponent extends React.Component {
constructor( props ) {
super( props )
// You probably want to be smarter about initially populating state
this.state = {
data: store.data
}
}
componentWillMount() {
store.on( 'update', data => this.setState({ data: data }) )
}
render() {
let cells = this.state.data.map( ( value, index ) => <ChildComponent index={ index } value={ value } /> )
return (
<div>
{ cells }
</div>
)
}
}
为简洁起见,这里的子组件直接告诉商店更改值,您可能希望分派 messages/actions 并让商店决定如何响应,关键是将商店数据传递给更新其状态并触发重新渲染的父组件。
这里的流程本质上是 UI 是愚蠢的,它只是呈现它从商店收集的数据,并在用户操作时发送一条消息告诉商店 update/mutate检测到(在这种情况下按下按钮,但听起来您需要某种输入),当商店中的数据发生变化时,它会发出(或者也可以使用调度程序)一个更改事件,该事件强制 UI 重新呈现新状态。由于在此阶段重新呈现子组件,它们会填充新的数据状态,确保您的 UI 保持一致。
我有一个 table 具有动态生成的列 headers 和行,用户可以在行中输入数据,当他们单击“保存”时,数据应保存到该行中,但在此刻它没有将值保存到 table 但它正在将它们保存在我的数据库中。理想情况下,我希望这样,当单击保存按钮时,数据将保存到该行,然后可以在该行中查看(如果这有意义的话)。
这是我正在使用的代码(我知道它现在一团糟!):
数据输入表单代码:
import React from 'react';
import AppStore from '../../stores/AppStore';
export default class RowForm extends React.Component {
state = {dataEntries: []};
onChange = (event, element) => {
let dataEntries = this.state.dataEntries;
dataEntries[element] = event.target.value;
this.setState({dataEntries});
};
editStop = () => {
this.props.editStop();
};
handleSubmit = (e) => {
e.preventDefault();
let access_token = AppStore.getToken();
let id = AppStore.getTable().id;
let dataEntries = this.state.dataEntries;
let dataEntriesArray = [];
for (let key in dataEntries) {
if (dataEntries.hasOwnProperty(key)) {
dataEntriesArray.push({contents: dataEntries[key]});
}
}
this.props.handleSubmit(access_token, id, dataEntriesArray);
};
componentDidMount() {
let nameArray = AppStore.getTable().columns.map((obj) => {
return obj.name;
});
let dataEntries = nameArray.reduce((obj, name) => {
obj[name] = null;
return obj;
}, {});
this.setState({dataEntries});
}
render() {
let {dataEntries} = this.state;
return (
<tr>
{Object.keys(dataEntries).map((element) => {
return (
<td key={element}><input type="text" className="form-control" id={element} placeholder="enter data" value={dataEntries[element]} onChange={event => this.onChange(event, element)} /></td>
);
})}
<td>
<button className="btn btn-default" onClick={this.editStop}><i className="fa fa-ban"></i>Cancel</button>
<button className="btn btn-success" onClick={this.handleSubmit}><i className="fa fa-check"></i>Save</button>
</td>
</tr>
);
}
数据输入并提交后(是一个objects的数组,如dataEntriesArray = [{contents: "value"}, {contents: "value"}, {contents : "value"}, {内容: "value"}].
这是我渲染 table 的方式(我认为这就是问题所在):
import React from 'react';
import TableHeader from './TableHeader.jsx';
import RowForm from './RowForm.jsx';
import {createRow} from '../../actions/DALIActions';
import AppStore from '../../stores/AppStore';
export default class Table extends React.Component {
state = {rows: [], isNew: false, isEditing: false};
handleAddRowClickEvent = () => {
let rows = this.state.rows;
rows.push({isNew: true});
this.setState({rows: rows, isEditing: false});
};
handleEdit = (row) => {
this.setState({isEditing: true});
};
editStop = () => {
this.setState({isEditing: false});
};
handleSubmit = (access_token, id, dataEntriesArray) => {
createRow(access_token, id, dataEntriesArray);
};
render() {
let {rows, isNew, isEditing} = this.state;
let headerArray = AppStore.getTable().columns;
return (
<div>
<div className="row" id="table-row">
<table className="table table-striped">
<thead>
<TableHeader />
</thead>
<tbody>
{rows.map((row, index) => this.state.isEditing ?
<RowForm formKey={index} key={index} editStop={this.editStop} handleSubmit={this.handleSubmit} /> :
<tr key={index}>
{headerArray.map((element, index) => {
return (
<td key={index} id={element.id}></td>
);
})}
<td>
<button className="btn btn-primary" onClick={this.handleEdit.bind(this, row)}><i className="fa fa-pencil"></i>Edit</button>
</td>
</tr>)}
</tbody>
</table>
</div>
<div className="row">
<div className="col-xs-12 de-button">
<button type="button" className="btn btn-success" onClick={this.handleAddRowClickEvent}>Add Row</button>
</div>
</div>
</div>
);
}
}
我目前正在使用 flux,并且理想情况下希望暂时继续使用它(我知道 redux,但理想情况下我希望在开始重构我的代码之前让它在 flux 中工作)。我怀疑我渲染 table.
的方式有问题非常感谢任何帮助,尤其是示例!
谢谢你的时间!
看起来您可能想将 table 数据提取到您的商店中,您的 UI 子元素触发更改事件,然后您的商店更新其数据并触发更改事件,您的父组件可以监听和更新。
类似于下面的简化示例,它改变了数组元素:
class Store extends EventEmitter {
constructor() {
super()
this.data = [ 'a', 'b', 'c' ]
}
onChange() {
this.emit( 'update', this.data )
}
mutate( index, value ) {
this.data[ index ] = value
this.onChange()
}
}
var store = new Store()
class ChildComponent extends React.Component {
constructor( props ) {
super( props )
}
// You probably want to use a dispatcher rather than directly accessing the store
onClick = event => {
store.mutate( this.props.index, this.props.value + 'Z' )
}
render() {
return <button onClick={ this.onClick }>{ this.props.value }</button>
}
}
class ParentComponent extends React.Component {
constructor( props ) {
super( props )
// You probably want to be smarter about initially populating state
this.state = {
data: store.data
}
}
componentWillMount() {
store.on( 'update', data => this.setState({ data: data }) )
}
render() {
let cells = this.state.data.map( ( value, index ) => <ChildComponent index={ index } value={ value } /> )
return (
<div>
{ cells }
</div>
)
}
}
为简洁起见,这里的子组件直接告诉商店更改值,您可能希望分派 messages/actions 并让商店决定如何响应,关键是将商店数据传递给更新其状态并触发重新渲染的父组件。
这里的流程本质上是 UI 是愚蠢的,它只是呈现它从商店收集的数据,并在用户操作时发送一条消息告诉商店 update/mutate检测到(在这种情况下按下按钮,但听起来您需要某种输入),当商店中的数据发生变化时,它会发出(或者也可以使用调度程序)一个更改事件,该事件强制 UI 重新呈现新状态。由于在此阶段重新呈现子组件,它们会填充新的数据状态,确保您的 UI 保持一致。