React - 从嵌套组件访问更新值
React - Accessing updated values from nested components
我有一个包含行的 table,行中的每个单元格都可以编辑。每行都有一个按钮,可以将该行中的所有单元格提交到数据库。我想知道的是,如果单元格中的数据已更改,我如何从实际发生提交事件的组件访问新值?
这是我目前构建 table 的方式:
主要Table:
import React from 'react';
import TableWithDataHeader from './TableWithDataHeader.jsx';
import Row from './Row.jsx';
import AppStore from '../../stores/AppStore';
export default class Table extends React.Component {
handleSubmitEvent = (e) => {
e.preventDefault();
/////What do I do here to get the updated values???////
};
render() {
return (
<div>
<div className="row">
<table className="table table-striped table-bordered">
<thead>
<TableWithDataHeader />
</thead>
<Row data={AppStore.getCells().historycells} handleSubmitEvent={this.handleSubmitEvent} />
</table>
</div>
</div>
);
}
}
行组件:
import React from 'react';
import TableBody from './TableBody.jsx';
import AppStore from '../../stores/AppStore';
export default class Row extends React.Component {
state = {data: this.props.data};
handleSubmitEvent = (e) => {
this.props.handleSubmitEvent(e);
};
render() {
let {data} = this.state;
return (
<tbody>
<tr id={AppStore.getRowId()}>
{this.state.data.map(cell => {
return (
<TableBody key={cell.id} cell={cell.contents} />
);
})}
<td className="table-button">
<button type="submit" className="btn btn-primary" onClick={this.handleSubmitEvent.bind(this)}>Save Row</button>
</td>
</tr>
</tbody>
);
}
}
单元格组件:
import React from 'react';
import EditableCells from './EditableCells.jsx';
export default class TableBody extends React.Component {
render() {
return (
<EditableCells data={this.props.cell} />
);
}
}
编辑单元格组件:
import React from 'react';
export default class EditableCells extends React.Component {
state = {isEditMode: false, data: ""};
componentWillMount() {
this.setState({
isEditMode: this.props.isEditMode,
data: this.props.data
});
}
handleEditCell = (e) => {
this.setState({isEditMode: true});
};
handleKeyDown = (e) => {
switch (e.keyCode) {
case 13: //Enter
this.setState({isEditMode: false});
break;
}
};
handleChange = (e) => {
this.setState({data: e.target.value});
};
render() {
let {isEditMode, data} = this.state;
let cellHtml;
if (this.state.isEditMode) {
cellHtml = <input type="text" className="form-control" value={this.state.data} onKeyDown={this.handleKeyDown} onChange={this.handleChange} />
} else {
cellHtml = <div onClick={this.handleEditCell}>{this.state.data}</div>
}
return (
<td className="text-center">{cellHtml}</td>
);
}
}
任何关于我如何能够做到这一点的帮助都会非常有帮助,当然,非常感谢!
感谢您的宝贵时间
尽量让您的应用程序状态处于组件树中的最高级别。在这种情况下,简单的方法是让 Table 组件处理数据状态,并提供事件处理程序。将它们作为道具传递给 Row,并根据需要进一步向下传递。概念验证:https://jsfiddle.net/dannyjolie/4jfxeag8/1/
一般的经验法则是根本不要使用组件状态,并利用应用程序更改中的所有更改到最顶层的组件,但输入字段有时是规则的例外,因为您可能不想修改输入时的应用程序状态。
它的基础知识:
export default class Table extends React.Component {
constructor(props) {
super(props);
this.state.cells = ['Foo', 'Bar']; // Fetch something from your store, or better, pass the cells as props from parent component
this.handleSubmitEvent = this.handleSubmitEvent.bind(this);
this.handleChangeEvent = this.handleChangeEvent.bind(this);
}
handleSubmitEvent () {
// Up to date cells are stored in this.state
}
handleChangeEvent (value, cell) {
// All values are available in this.state, do with that as you wish :)
}
render () {
....
<Row handleSubmitEvent={this.handleSubmitEvent}
handleChangeEvent={this.handleChangeEvent}
data={this.state.cells} />
....
}
}
React 仅注入数据更改,并在必要时从上到下重新渲染 DOM 更改的部分。你可以做的是通过道具让子组件访问父组件的状态:
class ParentComponent extends Component {
handleWhatever(updated) {
this.setState({
whatever: updated
});
}
render() {
return (
<ChildComponent onEdit={::this.handleWhatever} />
);
}
}
和
class ChildComponent extends Component {
render() {
return (
<SomethingEditable onChange={this.props.onEdit} />
);
}
}
所以,想法是:
- 在
ParentComponent
中,您定义了一个方法,该方法在被调用时会更改此组件的状态,即 ParentComponent
的状态。
- 在
ChildComponent
中,您拥有能够在每次更改时调用函数的东西(最常见的示例:input
元素及其 onBlur
事件) .
- 每次在
ChildComponent
中更改内容时,它都会调用从 ParentComponent
传递的函数,该函数依次从下到上提供数据并将其传递给ParentComponent
.
- 函数被调用,bound 到
ParentComponent
,所以 setState
被调用,这改变了 ParentComponent
的状态,它反映(或不反映)重新渲染整个子树(React 只负责挑选那些真正需要重新渲染的组件)。
这是解决数据移动方向与 React 预期数据流动方向相反的问题的经典方法。
您可以根据需要拥有任意多的嵌套层,只是不要忘记将该函数传递给所有层。
我有一个包含行的 table,行中的每个单元格都可以编辑。每行都有一个按钮,可以将该行中的所有单元格提交到数据库。我想知道的是,如果单元格中的数据已更改,我如何从实际发生提交事件的组件访问新值?
这是我目前构建 table 的方式:
主要Table:
import React from 'react';
import TableWithDataHeader from './TableWithDataHeader.jsx';
import Row from './Row.jsx';
import AppStore from '../../stores/AppStore';
export default class Table extends React.Component {
handleSubmitEvent = (e) => {
e.preventDefault();
/////What do I do here to get the updated values???////
};
render() {
return (
<div>
<div className="row">
<table className="table table-striped table-bordered">
<thead>
<TableWithDataHeader />
</thead>
<Row data={AppStore.getCells().historycells} handleSubmitEvent={this.handleSubmitEvent} />
</table>
</div>
</div>
);
}
}
行组件:
import React from 'react';
import TableBody from './TableBody.jsx';
import AppStore from '../../stores/AppStore';
export default class Row extends React.Component {
state = {data: this.props.data};
handleSubmitEvent = (e) => {
this.props.handleSubmitEvent(e);
};
render() {
let {data} = this.state;
return (
<tbody>
<tr id={AppStore.getRowId()}>
{this.state.data.map(cell => {
return (
<TableBody key={cell.id} cell={cell.contents} />
);
})}
<td className="table-button">
<button type="submit" className="btn btn-primary" onClick={this.handleSubmitEvent.bind(this)}>Save Row</button>
</td>
</tr>
</tbody>
);
}
}
单元格组件:
import React from 'react';
import EditableCells from './EditableCells.jsx';
export default class TableBody extends React.Component {
render() {
return (
<EditableCells data={this.props.cell} />
);
}
}
编辑单元格组件:
import React from 'react';
export default class EditableCells extends React.Component {
state = {isEditMode: false, data: ""};
componentWillMount() {
this.setState({
isEditMode: this.props.isEditMode,
data: this.props.data
});
}
handleEditCell = (e) => {
this.setState({isEditMode: true});
};
handleKeyDown = (e) => {
switch (e.keyCode) {
case 13: //Enter
this.setState({isEditMode: false});
break;
}
};
handleChange = (e) => {
this.setState({data: e.target.value});
};
render() {
let {isEditMode, data} = this.state;
let cellHtml;
if (this.state.isEditMode) {
cellHtml = <input type="text" className="form-control" value={this.state.data} onKeyDown={this.handleKeyDown} onChange={this.handleChange} />
} else {
cellHtml = <div onClick={this.handleEditCell}>{this.state.data}</div>
}
return (
<td className="text-center">{cellHtml}</td>
);
}
}
任何关于我如何能够做到这一点的帮助都会非常有帮助,当然,非常感谢!
感谢您的宝贵时间
尽量让您的应用程序状态处于组件树中的最高级别。在这种情况下,简单的方法是让 Table 组件处理数据状态,并提供事件处理程序。将它们作为道具传递给 Row,并根据需要进一步向下传递。概念验证:https://jsfiddle.net/dannyjolie/4jfxeag8/1/
一般的经验法则是根本不要使用组件状态,并利用应用程序更改中的所有更改到最顶层的组件,但输入字段有时是规则的例外,因为您可能不想修改输入时的应用程序状态。
它的基础知识:
export default class Table extends React.Component {
constructor(props) {
super(props);
this.state.cells = ['Foo', 'Bar']; // Fetch something from your store, or better, pass the cells as props from parent component
this.handleSubmitEvent = this.handleSubmitEvent.bind(this);
this.handleChangeEvent = this.handleChangeEvent.bind(this);
}
handleSubmitEvent () {
// Up to date cells are stored in this.state
}
handleChangeEvent (value, cell) {
// All values are available in this.state, do with that as you wish :)
}
render () {
....
<Row handleSubmitEvent={this.handleSubmitEvent}
handleChangeEvent={this.handleChangeEvent}
data={this.state.cells} />
....
}
}
React 仅注入数据更改,并在必要时从上到下重新渲染 DOM 更改的部分。你可以做的是通过道具让子组件访问父组件的状态:
class ParentComponent extends Component {
handleWhatever(updated) {
this.setState({
whatever: updated
});
}
render() {
return (
<ChildComponent onEdit={::this.handleWhatever} />
);
}
}
和
class ChildComponent extends Component {
render() {
return (
<SomethingEditable onChange={this.props.onEdit} />
);
}
}
所以,想法是:
- 在
ParentComponent
中,您定义了一个方法,该方法在被调用时会更改此组件的状态,即ParentComponent
的状态。 - 在
ChildComponent
中,您拥有能够在每次更改时调用函数的东西(最常见的示例:input
元素及其onBlur
事件) . - 每次在
ChildComponent
中更改内容时,它都会调用从ParentComponent
传递的函数,该函数依次从下到上提供数据并将其传递给ParentComponent
. - 函数被调用,bound 到
ParentComponent
,所以setState
被调用,这改变了ParentComponent
的状态,它反映(或不反映)重新渲染整个子树(React 只负责挑选那些真正需要重新渲染的组件)。
这是解决数据移动方向与 React 预期数据流动方向相反的问题的经典方法。
您可以根据需要拥有任意多的嵌套层,只是不要忘记将该函数传递给所有层。