如何在父组件和子组件之间动态设置状态()
How to setState() dynamically in between Parent and Child Component [Logic being run on child & state on the Root App level]
我在学习 React 时正在闲逛,我想知道对于下面介绍的场景,什么是优雅的解决方案。
按照此 Link 查看完整的代码集。
我有一个 child
组件,它有一个 <h1>
tag
。此标记 returns 我正在动态显示的消息,如下所示。
应用根容器
我的 state
在这个 container
上,我想把它放在那里。
状态:
这里讨论的对象是cockpitAlert
object
.
state = {
state = {
persons: [
{ id: "a", name: "foo1" },
{ id: "b", name: "foo2" },
{ id: "c", name: "foo3" }
],
CockpitAlert: {
regular: "Some message",
alert1: "The array is ending",
alert2: "There is nothing to show"
}
};
下面是我如何删除渲染的项目 - 仍然在 App.js
personDeleteHandler = index => {
const person = [...this.state.persons];
person.splice(index, 1);
this.setState({ persons: person });
};
下面是我渲染 JSX
的地方
render() {
return (
<div className="App">
<Cockpit
regular={this.state.CockpitAlert.regular}
alert1={this.state.CockpitAlert.alert1}
alert2={this.state.CockpitAlert.alert2}
personsLength={this.state.persons.length}
/>
<Person click={this.personDeleteHandler} persons={this.state.persons} />
</div>
);
}
座舱子
逻辑如下。 let message
根据 persons
array
的长度动态更改 props
,点击后会缩短。
import React from "react";
function Cockpit(props) {
let message = props.regular;
if (props.personsLength <= 2) {
message = props.alert1;
}
if (props.personsLength === 0) {
message = props.alert2;
}
return (
<div>
<h1>{message}</h1>
</div>
);
}
export default Cockpit;
如您所见,这看起来一点也不好看。
我不想让所有这些不同的 props
都指向我的逻辑:
regular={this.state.CockpitAlert.regular}
alert1={this.state.CockpitAlert.alert1}
alert2={this.state.CockpitAlert.alert2}
personsLength={this.state.persons.length}
我想知道是否有一种方法可以只传递一个 props
,例如 props.message
并动态更改它,可能是通过 setState()
在 root
级别,其中设置 state
而无需将我的逻辑从 Cockpit
移动到 App.js
您可以将函数传递给子组件。定义消息后,它会调用带有消息参数的函数。 Parent 然后通过函数接收消息。
// Example class component
class Parent extends React.Component {
state = {
message: ""
}
updateMessage = message => {
this.setState({
message: message
});
}
render() {
return (
<div>
<div><b>This is my parent</b></div>
<Child
usersLength={0}
alert1="Alert1"
alert2="Alert2"
alert3="Alert3"
updateMessage={this.updateMessage}
>
</Child>
<Child
usersLength={1}
alert1="Alert1"
alert2="Alert2"
alert3="Alert3"
updateMessage={this.updateMessage}
>
</Child>
<Child
usersLength={2}
alert1="Alert1"
alert2="Alert2"
alert3="Alert3"
updateMessage={this.updateMessage}
>
</Child>
</div>
);
}
}
class Child extends React.Component {
constructor(props) {
super(props);
const {usersLength, alert1, alert2, alert3} = props;
let message = "";
if(usersLength <= 2)
message = alert1;
if(usersLength <= 1)
message = alert2;
if(usersLength === 0)
message = alert3;
this.state = {
message : message
}
props.updateMessage(message);
}
render() {
const {message} = this.state;
return <p>My child message is : {message}</p>
}
}
// Render it
ReactDOM.render(
<Parent />,
document.getElementById("react")
);
<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="react"></div>
好吧,我发现了如何使用 React Context API
解决这个问题
这是更新后的 CodeSandBox
我首先创建了文件 auth-context.js
,以便将我的状态从 Parent
组件传递到 child
组件。
由于逻辑已经基于 Cockpit.js
,在这种情况下,我只会通过 React Context ApI
传递我的 state
。
auth-context.js
文件
import React from 'react'
const authContext = React.createContext({
persons: [
{ id: "a", name: "foo1" },
{ id: "b", name: "foo2" },
{ id: "c", name: "foo3" }
],
message: "Some message",
});
export default authContext
在我的 App.js 容器上
现在我已经在 App.js
root
容器中设置了 Provider
:
//first of all, import the file into the root element which will Provide the //initial state on this API
import AuthContext from "./Context/auth-context";
...
class App extends Component {
state = {
persons: [
{ id: "a", name: "foo1" },
{ id: "b", name: "foo2" },
{ id: "c", name: "foo3" }
],
CockpitAlert: {
message: "Some message"
}
};
personDeleteHandler = index => {
const person = [...this.state.persons];
person.splice(index, 1);
this.setState({ persons: person });
};
render() {
return (
<div className="App">
//I am wrapping the whole deal here and set my state so I can manage it at
// the Cockpit.js file further on
<AuthContext.Provider
value={{
persons: this.state.persons,
message: this.state.CockpitAlert.message
}}
>
//no more props being passed at Cockpit.js!!!
<Cockpit />
<Person
click={this.personDeleteHandler}
persons={this.state.persons}
/>
</AuthContext.Provider>
</div>
);
}
}
export default App;
现在我将 state
传递给子组件
Cockpit.js
文件
import React, { useContext } from "react";
//must import AuthContent here as well.
import AuthContext from "../../Context/auth-context";
function Cockpit(props) {
//this is the way of setting it up on a functional component
// now I have access to the state through authContext
const authContext = useContext(AuthContext);
//here I will point my state into different messages
if (authContext.persons.length <= 2) {
authContext.message = "running out";
}
if (authContext.persons.length === 0) {
authContext.message = "nothing else to render";
}
//as you can see there are no props created
return <div>{<h1>{authContext.message}</h1>}</div>;
}
export default Cockpit;
现在我的想法是:
这不会改变 App.js
处的原始状态。在这种情况下,这是一个好的做法吗?
大家怎么看?
我在学习 React 时正在闲逛,我想知道对于下面介绍的场景,什么是优雅的解决方案。
按照此 Link 查看完整的代码集。
我有一个 child
组件,它有一个 <h1>
tag
。此标记 returns 我正在动态显示的消息,如下所示。
应用根容器
我的 state
在这个 container
上,我想把它放在那里。
状态:
这里讨论的对象是cockpitAlert
object
.
state = {
state = {
persons: [
{ id: "a", name: "foo1" },
{ id: "b", name: "foo2" },
{ id: "c", name: "foo3" }
],
CockpitAlert: {
regular: "Some message",
alert1: "The array is ending",
alert2: "There is nothing to show"
}
};
下面是我如何删除渲染的项目 - 仍然在 App.js
personDeleteHandler = index => {
const person = [...this.state.persons];
person.splice(index, 1);
this.setState({ persons: person });
};
下面是我渲染 JSX
render() {
return (
<div className="App">
<Cockpit
regular={this.state.CockpitAlert.regular}
alert1={this.state.CockpitAlert.alert1}
alert2={this.state.CockpitAlert.alert2}
personsLength={this.state.persons.length}
/>
<Person click={this.personDeleteHandler} persons={this.state.persons} />
</div>
);
}
座舱子
逻辑如下。 let message
根据 persons
array
的长度动态更改 props
,点击后会缩短。
import React from "react";
function Cockpit(props) {
let message = props.regular;
if (props.personsLength <= 2) {
message = props.alert1;
}
if (props.personsLength === 0) {
message = props.alert2;
}
return (
<div>
<h1>{message}</h1>
</div>
);
}
export default Cockpit;
如您所见,这看起来一点也不好看。
我不想让所有这些不同的 props
都指向我的逻辑:
regular={this.state.CockpitAlert.regular}
alert1={this.state.CockpitAlert.alert1}
alert2={this.state.CockpitAlert.alert2}
personsLength={this.state.persons.length}
我想知道是否有一种方法可以只传递一个 props
,例如 props.message
并动态更改它,可能是通过 setState()
在 root
级别,其中设置 state
而无需将我的逻辑从 Cockpit
移动到 App.js
您可以将函数传递给子组件。定义消息后,它会调用带有消息参数的函数。 Parent 然后通过函数接收消息。
// Example class component
class Parent extends React.Component {
state = {
message: ""
}
updateMessage = message => {
this.setState({
message: message
});
}
render() {
return (
<div>
<div><b>This is my parent</b></div>
<Child
usersLength={0}
alert1="Alert1"
alert2="Alert2"
alert3="Alert3"
updateMessage={this.updateMessage}
>
</Child>
<Child
usersLength={1}
alert1="Alert1"
alert2="Alert2"
alert3="Alert3"
updateMessage={this.updateMessage}
>
</Child>
<Child
usersLength={2}
alert1="Alert1"
alert2="Alert2"
alert3="Alert3"
updateMessage={this.updateMessage}
>
</Child>
</div>
);
}
}
class Child extends React.Component {
constructor(props) {
super(props);
const {usersLength, alert1, alert2, alert3} = props;
let message = "";
if(usersLength <= 2)
message = alert1;
if(usersLength <= 1)
message = alert2;
if(usersLength === 0)
message = alert3;
this.state = {
message : message
}
props.updateMessage(message);
}
render() {
const {message} = this.state;
return <p>My child message is : {message}</p>
}
}
// Render it
ReactDOM.render(
<Parent />,
document.getElementById("react")
);
<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="react"></div>
好吧,我发现了如何使用 React Context API
这是更新后的 CodeSandBox
我首先创建了文件 auth-context.js
,以便将我的状态从 Parent
组件传递到 child
组件。
由于逻辑已经基于 Cockpit.js
,在这种情况下,我只会通过 React Context ApI
传递我的 state
。
auth-context.js
文件
import React from 'react'
const authContext = React.createContext({
persons: [
{ id: "a", name: "foo1" },
{ id: "b", name: "foo2" },
{ id: "c", name: "foo3" }
],
message: "Some message",
});
export default authContext
在我的 App.js 容器上
现在我已经在 App.js
root
容器中设置了 Provider
:
//first of all, import the file into the root element which will Provide the //initial state on this API
import AuthContext from "./Context/auth-context";
...
class App extends Component {
state = {
persons: [
{ id: "a", name: "foo1" },
{ id: "b", name: "foo2" },
{ id: "c", name: "foo3" }
],
CockpitAlert: {
message: "Some message"
}
};
personDeleteHandler = index => {
const person = [...this.state.persons];
person.splice(index, 1);
this.setState({ persons: person });
};
render() {
return (
<div className="App">
//I am wrapping the whole deal here and set my state so I can manage it at
// the Cockpit.js file further on
<AuthContext.Provider
value={{
persons: this.state.persons,
message: this.state.CockpitAlert.message
}}
>
//no more props being passed at Cockpit.js!!!
<Cockpit />
<Person
click={this.personDeleteHandler}
persons={this.state.persons}
/>
</AuthContext.Provider>
</div>
);
}
}
export default App;
现在我将 state
传递给子组件
Cockpit.js
文件
import React, { useContext } from "react";
//must import AuthContent here as well.
import AuthContext from "../../Context/auth-context";
function Cockpit(props) {
//this is the way of setting it up on a functional component
// now I have access to the state through authContext
const authContext = useContext(AuthContext);
//here I will point my state into different messages
if (authContext.persons.length <= 2) {
authContext.message = "running out";
}
if (authContext.persons.length === 0) {
authContext.message = "nothing else to render";
}
//as you can see there are no props created
return <div>{<h1>{authContext.message}</h1>}</div>;
}
export default Cockpit;
现在我的想法是:
这不会改变 App.js
处的原始状态。在这种情况下,这是一个好的做法吗?
大家怎么看?