我正在与React一起工作。我的想法是创建一个可重用的Form组件,该组件从Page组件获取状态作为道具,并将保留使用子数据更新其自身状态的逻辑,并将其发送给父Page组件。
Page组件是这样的:
class Page extends Component {
constructor(props) {
super(props);
this.state = {
data: {
text1: "Initial text1",
text2: "Initial text2"
}
};
}
render() {
return (
<div className="Page">
<div className="DataPreview">
Data preview in Page component
<div>{this.state.data.text1}</div>
<div>{this.state.data.text2}</div>
</div>
<Form data={this.state.data}>
<Input id="text1" data={this.state.data.text1} />
<Input id="text2" data={this.state.data.text2} />
</Form>
</div>
);
}
}
这是表单组件:
class Form extends Component {
constructor(props) {
super(props);
this.state = this.props.data;
}
render() {
return (
<div className="Parent">
<div>Form component</div>
<div className="DataPreview">
Data preview in Form component
<div>{this.state.text1}</div>
<div>{this.state.text2}</div>
</div>
{this.props.children}
</div>
);
}
}
这是输入组件:
class Input extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="Child" id={this.props.id}>
<div>Input component</div>
<input id={this.props.id} type="text" value={this.props.data} />
</div>
);
}
}
因此Input应该更新Form状态,而Form应该更新Page状态。我知道如何在将Input写入Form组件内部时通过回调传递信息,但是像这种情况一样,我无法弄清楚如何将其写入Page组件内部。
我为有兴趣的人提供了一个沙箱:https://codesandbox.io/s/qx6kqypo09
答案 0 :(得分:1)
class Input extends Component {
constructor(props) {
super(props);
}
handleChange(e) {
let data = this.props.this.state.data;
data.text1 = e.target.value;
this.props.this.setState({ data: data });
}
render() {
return (
<div className="Child" id={this.props.id}>
<div>Input component {this.props.id}</div>
<input
id={this.props.id}
type="text"
value={this.props.data}
onChange={e => this.handleChange(e)}
/>
</div>
);
}
}
使用指定的输入组件和如下所述的页面组件-
class Page extends Component {
constructor(props) {
super(props);
this.state = {
data: {
text1: "Initial text1",
text2: "Initial text2"
}
};
}
render() {
return (
<div className="Page">
<div className="DataPreview">
Data preview in Page component
<div>{this.state.data.text1}</div>
<div>{this.state.data.text2}</div>
</div>
<Form data={this.state.data}>
<Input id="text1" this={this} data={this.state.data.text1} />
<Input id="text2" data={this.state.data.text2} />
</Form>
</div>
);
}
}
我认为这对您有帮助 谢谢
答案 1 :(得分:1)
正如@dashton所说,我在不同组件中保持相同状态,这是不正确的。我将寻找一种不同的方法,而不是仅使用Form
组件状态,并通过组合共享逻辑。我将为此提出一个新问题。
答案 2 :(得分:0)
在不使用某种状态管理的情况下,您将需要创建一个方法来处理父组件中的状态更改,然后将其作为道具传递给子组件。
一旦在子组件中调用该方法,它将更新父组件的状态。
答案 3 :(得分:0)
这是您要实现的目标的一种方法:传递onChange
的回调处理程序。但是,当您的应用开始变大时,可能会很丑陋:)如果您正在考虑创建一个复杂的可重用Form
组件,则可以检查当前的节点包。
该方法的替代方法,如果您需要一个简单的方法,则可以稍微研究一下React Context。它可以帮助您。除了Redux之外,其他全局状态管理库也可以做到这一点。
class Page extends React.Component {
state = {
data: {
text1: "Initial text1",
text2: "Initial text2",
},
};
handleChange = ( e ) => {
const { name, value } = e.target;
this.setState( prevState => ( {
data: { ...prevState.data, [ name ]: value },
} ) );
}
render() {
return (
<div className="Page">
<div className="DataPreview">
Data preview in Page component
<div>{this.state.data.text1}</div>
<div>{this.state.data.text2}</div>
</div>
<Form data={this.state.data}>
<Input name="text1" data={this.state.data.text1} onChange={this.handleChange} />
<Input name="text2" data={this.state.data.text2} onChange={this.handleChange} />
</Form>
</div>
);
}
}
const Form = props => (
<div className="Parent">
<div>Form component</div>
<div className="DataPreview">
Data preview in Form component
<div>{props.data.text1}</div>
<div>{props.data.text2}</div>
</div>
{props.children}
</div>
);
const Input = props => (
<div className="Child" id={props.id}>
<div>Input component {props.id}</div>
<input name={props.name} type="text" value={props.data} onChange={props.onChange} />
</div>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<Page />, rootElement);
.Page {
border: 10px solid blue;
}
.Parent {
border: 10px solid turquoise;
}
.Child {
border: 3px solid tomato;
}
.DataPreview {
border: 3px solid lightgray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
答案 4 :(得分:0)
正如其他人所说,您在不同组件中拥有相同的状态,这显然是不正确的。
但是,要满足您关于将子组件与表单分离的要求,您可以使用render道具使表单处理输入的状态变化,该道具会将回调传递给输入,请参见代码和链接
https://codesandbox.io/s/4zyvjm0q64
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class Input extends Component {
constructor(props) {
super(props);
}
handleChange(id, value) {
this.props.onChange(id, value);
}
render() {
return (
<div className="Child" id={this.props.id}>
<div>Input component {this.props.id}</div>
<input
id={this.props.id}
type="text"
value={this.props.data}
onChange={e => this.handleChange(e)}
/>
</div>
);
}
}
class Form extends Component {
constructor(props) {
super(props);
this.state = this.props.data;
}
handleChange = (id, value) => {
this.setState({ [id]: value });
};
render() {
return (
<div className="Parent">
<div>Form component</div>
<div className="DataPreview">
Data preview in Form component
<div>{this.state.text1}</div>
<div>{this.state.text2}</div>
</div>
{this.props.render(this.handleChange)}
</div>
);
}
}
class Page extends Component {
constructor(props) {
super(props);
this.state = {
data: {
text1: "Initial text1",
text2: "Initial text2"
}
};
}
render() {
return (
<div className="Page">
<div className="DataPreview">
Data preview in Page component
<div>{this.state.data.text1}</div>
<div>{this.state.data.text2}</div>
</div>
<Form
data={this.state.data}
render={(handler) => {
return (
<div>
<Input id="text1" onChange={e => handler("text1", e.target.value)} />
<Input id="text2" onChange={e => handler("text2", e.target.value)} />
</div>
);
}}
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Page />, rootElement);