我的结构如下所示:
Component 1
- |- Component 2
- - |- Component 4
- - - |- Component 5
Component 3
组件3应该根据组件5的状态显示一些数据。
因为道具是不可变的,我不能简单地在组件1中保存它的状态并转发它,对吗?是的,我读过Redux,但我不想使用它。我希望只用react就能解决这个问题。我错了吗?
我的结构如下所示:
Component 1
- |- Component 2
- - |- Component 4
- - - |- Component 5
Component 3
组件3应该根据组件5的状态显示一些数据。
因为道具是不可变的,我不能简单地在组件1中保存它的状态并转发它,对吗?是的,我读过Redux,但我不想使用它。我希望只用react就能解决这个问题。我错了吗?
当前回答
下面是获得两种绑定数据方式的简短代码片段。
计数器显示来自父进程的值,并从子进程更新
class Parent extends React.Component { constructor(props) { super(props) this.handler = this.handler.bind(this) this.state = { count: 0 } } handler() { this.setState({ count: this.state.count + 1 }) } render() { return <Child handler={this.handler} count={this.state.count} /> } } class Child extends React.Component { render() { return <button onClick={this.props.handler}>Count {this.props.count}</button> } } ReactDOM.render(<Parent />, document.getElementById("root")); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id="root"></div>
其他回答
对于子-父通信,您应该传递一个函数来设置从父到子的状态,如下所示
class Parent extends React.Component {
constructor(props) {
super(props)
this.handler = this.handler.bind(this)
}
handler() {
this.setState({
someVar: 'some value'
})
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <Button onClick = {this.props.handler}/ >
}
}
这样,子进程就可以通过调用带有props的函数来更新父进程的状态。
但是你必须重新考虑组件的结构,因为根据我的理解,组件5和组件3是不相关的。
一种可能的解决方案是将它们包装在一个更高级别的组件中,该组件将同时包含组件1和组件3的状态。该组件将通过props设置较低级别的状态。
父组件
function Parent() {
const [value, setValue] = React.useState("");
function handleChange(newValue) {
setValue(newValue);
}
// We pass a callback to Child
return <Child value={value} onChange={handleChange} />;
}
子组件
function Child(props) {
function handleChange(event) {
// Here, we invoke the callback with the new value
props.onChange(event.target.value);
}
return <input value={props.value} onChange={handleChange} />
}
我是这样做的:
type ParentProps = {}
type ParentState = { someValue: number }
class Parent extends React.Component<ParentProps, ParentState> {
constructor(props: ParentProps) {
super(props)
this.state = { someValue: 0 }
this.handleChange = this.handleChange.bind(this)
}
handleChange(value: number) {
this.setState({...this.state, someValue: value})
}
render() {
return <div>
<Child changeFunction={this.handleChange} defaultValue={this.state.someValue} />
<p>Value: {this.state.someValue}</p>
</div>
}
}
type ChildProps = { defaultValue: number, changeFunction: (value: number) => void}
type ChildState = { anotherValue: number }
class Child extends React.Component<ChildProps, ChildState> {
constructor(props: ChildProps) {
super(props)
this.state = { anotherValue: this.props.defaultValue }
this.handleChange = this.handleChange.bind(this)
}
handleChange(value: number) {
this.setState({...this.state, anotherValue: value})
this.props.changeFunction(value)
}
render() {
return <div>
<input onChange={event => this.handleChange(Number(event.target.value))} type='number' value={this.state.anotherValue}/>
</div>
}
}
如果你想要更新父组件,
class ParentComponent extends React.Component {
constructor(props){
super(props);
this.state = {
page: 0
}
}
handler(val){
console.log(val) // 1
}
render(){
return (
<ChildComponent onChange={this.handler} />
)
}
}
class ChildComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 1
};
}
someMethod = (page) => {
this.setState({ page: page });
this.props.onChange(page)
}
render() {
return (
<Button
onClick={() => this.someMethod()}
> Click
</Button>
)
}
}
这里的onChange是一个带有“handler”方法绑定到其实例的属性。我们将方法处理程序传递给子类组件,通过props参数中的onChange属性接收。
onChange属性将在props对象中设置,如下所示:
props = {
onChange: this.handler
}
并传递给子组件。
所以子组件可以像props. onchange这样访问props对象中的name值。
这是通过使用渲染道具完成的。
现在子组件有一个按钮“Click”,带有一个onclick事件集,用于调用通过props参数对象中的onChange传递给它的处理程序方法。所以现在子类中的this.props.onChange保存了父类中的输出方法。
参考资料和演职员表:Bits and Pieces
如果同样的场景不是到处都有,你可以使用React的上下文,特别是如果你不想引入状态管理库所引入的所有开销。另外,它更容易学习。但是要小心;你可能会过度使用它并开始编写糟糕的代码。基本上,你定义了一个Container组件(它将保存并为你保存这段状态),使得所有的组件都对从它的子组件(不一定是直接的子组件)写入/读取这段数据感兴趣。
背景信息-反应
你也可以使用一个普通的React来代替。
<Component5 onSomethingHappenedIn5={this.props.doSomethingAbout5} />
将doSomethingAbout5传递给组件1:
<Component1>
<Component2 onSomethingHappenedIn5={somethingAbout5 => this.setState({somethingAbout5})}/>
<Component5 propThatDependsOn5={this.state.somethingAbout5}/>
<Component1/>
如果这是一个常见问题,那么您应该开始考虑将应用程序的整个状态转移到其他地方。你有几个选择,最常见的是:
回来的 通量
基本上,不是在组件中管理应用程序状态,而是在发生更新状态的情况时发送命令。组件也从这个容器中提取状态,因此所有数据都是集中的。这并不意味着您不能再使用局部状态,但这是一个更高级的主题。