我的结构如下所示:
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就能解决这个问题。我错了吗?
当前回答
关于你的问题,我理解你需要在Component 3中显示一些基于Component 5状态的条件数据。方法:
组件3的状态将保存一个变量来检查组件5的状态是否有该数据 一个箭头函数,它将改变组件3的状态变量。 向组件5传递一个带有道具的箭头函数。 组件5有一个箭头函数,它将改变组件3的状态变量 组件5的箭头函数在加载自身时调用
<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> Class Component3 extends React.Component { state = { someData = true } checkForData = (result) => { this.setState({someData : result}) } render() { if(this.state.someData) { return( <Component5 hasData = {this.checkForData} /> //Other Data ); } else { return( //Other Data ); } } } export default Component3; class Component5 extends React.Component { state = { dataValue = "XYZ" } checkForData = () => { if(this.state.dataValue === "XYZ") { this.props.hasData(true); } else { this.props.hasData(false); } } render() { return( <div onLoad = {this.checkForData}> //Conditional Data </div> ); } } export default Component5;
其他回答
对于子-父通信,您应该传递一个函数来设置从父到子的状态,如下所示
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设置较低级别的状态。
当您需要在子节点和父节点之间进行任何级别的通信时,最好利用上下文。在父组件中定义可以被子组件调用的上下文,例如:
在父组件中,在你的案例中,组件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的上下文,特别是如果你不想引入状态管理库所引入的所有开销。另外,它更容易学习。但是要小心;你可能会过度使用它并开始编写糟糕的代码。基本上,你定义了一个Container组件(它将保存并为你保存这段状态),使得所有的组件都对从它的子组件(不一定是直接的子组件)写入/读取这段数据感兴趣。
背景信息-反应
你也可以使用一个普通的React来代替。
<Component5 onSomethingHappenedIn5={this.props.doSomethingAbout5} />
将doSomethingAbout5传递给组件1:
<Component1>
<Component2 onSomethingHappenedIn5={somethingAbout5 => this.setState({somethingAbout5})}/>
<Component5 propThatDependsOn5={this.state.somethingAbout5}/>
<Component1/>
如果这是一个常见问题,那么您应该开始考虑将应用程序的整个状态转移到其他地方。你有几个选择,最常见的是:
回来的 通量
基本上,不是在组件中管理应用程序状态,而是在发生更新状态的情况时发送命令。组件也从这个容器中提取状态,因此所有数据都是集中的。这并不意味着您不能再使用局部状态,但这是一个更高级的主题。
只需通过props将父组件的setState函数传递给子组件。
function ParentComp() {
const [searchValue, setSearchValue] = useState("");
return <SearchBox setSearchValue={setSearchValue} searchValue={searchValue} />;
}
然后在子组件中:
function SearchBox({ searchValue, setSearchValue }) {
return (
<input
id="search-post"
type="text"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
placeholder="Search Blogs ..."
/>
)
}
处理子组件点击的第二个例子:
// We've below function and component in parent component
const clickHandler = (val) => {
alert(`httpRequest sent. \nValue Received: ${val}`);
};
// JSX
<HttpRequest clickHandler={clickHandler} />
这就是你如何从父组件中获取函数,然后传递一个值并通过它触发clickHandler。
function HttpRequest({ clickHandler }) {
const [content, setContent] = useState("initialState");
return (
<button onClick={() => clickHandler(content)}>
Send Request
</button>
);
}
export default HttpRequest;
在React中,数据不能从子节点传递到父节点。数据必须从父节点传递给子节点。在这种情况下,您可以使用内置的Context API或第三方状态管理解决方案,如Redux、Mobx或Apollo GraphQL。然而,如果你的应用程序结构太小,你可以将数据存储在你的父元素中,然后通过prop drilling将其发送给你的子元素。但如果你的项目比较大,就会很混乱。