我的结构如下所示:
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就能解决这个问题。我错了吗?
当前回答
当您需要在子节点和父节点之间进行任何级别的通信时,最好利用上下文。在父组件中定义可以被子组件调用的上下文,例如:
在父组件中,在你的案例中,组件3,
static childContextTypes = {
parentMethod: React.PropTypes.func.isRequired
};
getChildContext() {
return {
parentMethod: (parameter_from_child) => this.parentMethod(parameter_from_child)
};
}
parentMethod(parameter_from_child){
// Update the state with parameter_from_child
}
现在在子组件中(在你的例子中是组件5),只需告诉这个组件它想要使用它的父组件的上下文。
static contextTypes = {
parentMethod: React.PropTypes.func.isRequired
};
render() {
return(
<TouchableHighlight
onPress = {() => this.context.parentMethod(new_state_value)}
underlayColor='gray' >
<Text> update state in parent component </Text>
</TouchableHighlight>
)}
您可以在这个GitHub存储库中找到Demo项目。
其他回答
似乎我们只能将数据从父组件传递给子组件,因为React促进单向数据流,但为了让父组件在“子组件”中发生某些事情时更新自己,我们通常使用所谓的“回调函数”。
我们将父类中定义的函数作为“props”传递给子类 从子进程调用该函数,在父进程中触发它 组件。
class Parent extends React.Component {
handler = (Value_Passed_From_SubChild) => {
console.log("Parent got triggered when a grandchild button was clicked");
console.log("Parent->Child->SubChild");
console.log(Value_Passed_From_SubChild);
}
render() {
return <Child handler = {this.handler} />
}
}
class Child extends React.Component {
render() {
return <SubChild handler = {this.props.handler}/ >
}
}
class SubChild extends React.Component {
constructor(props){
super(props);
this.state = {
somethingImp : [1,2,3,4]
}
}
render() {
return <button onClick = {this.props.handler(this.state.somethingImp)}>Clickme<button/>
}
}
React.render(<Parent />,document.getElementById('app'));
HTML
----
<div id="app"></div>
在这个例子中,我们可以通过将函数传递给它的直接子函数来实现数据从子→子→父的传递。
你可以通过将父对象的引用传递给子对象来实现,如下所示:
在A.js中有一个带有updateAState方法的父组件a 在B.js中有一个子组件B 有一个包装器函数,在C.js中呈现< a ><B></B></ a > 在C.js中,你可以像下面这样使用useRef:
import React, {useRef} from " React "; 导出默认函数C() { const parentARef = useRef(); const handleChildBClick = () => parentARef.current.updateAState(); 回报( < ref = {parentARef} > < B onClick = {handleChildBClick} > < / B > < / > ); }
指南参考:https://stackoverflow.com/a/56496607/1770571
如果同样的场景不是到处都有,你可以使用React的上下文,特别是如果你不想引入状态管理库所引入的所有开销。另外,它更容易学习。但是要小心;你可能会过度使用它并开始编写糟糕的代码。基本上,你定义了一个Container组件(它将保存并为你保存这段状态),使得所有的组件都对从它的子组件(不一定是直接的子组件)写入/读取这段数据感兴趣。
背景信息-反应
你也可以使用一个普通的React来代替。
<Component5 onSomethingHappenedIn5={this.props.doSomethingAbout5} />
将doSomethingAbout5传递给组件1:
<Component1>
<Component2 onSomethingHappenedIn5={somethingAbout5 => this.setState({somethingAbout5})}/>
<Component5 propThatDependsOn5={this.state.somethingAbout5}/>
<Component1/>
如果这是一个常见问题,那么您应该开始考虑将应用程序的整个状态转移到其他地方。你有几个选择,最常见的是:
回来的 通量
基本上,不是在组件中管理应用程序状态,而是在发生更新状态的情况时发送命令。组件也从这个容器中提取状态,因此所有数据都是集中的。这并不意味着您不能再使用局部状态,但这是一个更高级的主题。
这是如何使用新的useState钩子。
方法-将状态改变器函数作为道具传递给子组件,并对该函数做任何你想做的事情:
import React, {useState} from 'react';
const ParentComponent = () => {
const[state, setState]=useState('');
return(
<ChildComponent stateChanger={setState} />
)
}
const ChildComponent = ({stateChanger, ...rest}) => {
return(
<button onClick={() => stateChanger('New data')}></button>
)
}
我已经多次使用这个页面的顶级答案,但在学习React的时候,我发现了一个更好的方法,没有绑定,也没有道具内的内联函数。
看看这里:
class Parent extends React.Component {
constructor() {
super();
this.state = {
someVar: value
}
}
handleChange = (someValue) => {
this.setState({someVar: someValue})
}
render() {
return <Child handler={this.handleChange} />
}
}
export const Child = ({handler}) => {
return <Button onClick={handler} />
}
键在一个箭头函数中:
handleChange = (someValue) => {
this.setState({someVar: someValue})
}
你可以在这里阅读更多。