React 组件之间的传值
React遵循单向传输原则,所以尽量不要使用双向传值,容易导致循环更新问题。同时应该在创造组件时思考组件是否需要状态管理,如果不需要使用函数式声明更佳!
父向子传值
父向子传值起始比较简单,主要考虑向下传值是否会使得父组件中的状态过于繁杂,影响页面性能。
- 最简单的向子传值
- 父组件- Father Component
import { Component } from "react";
import PropTypes from "prop-types";
export default class Father extends Component {
constructor() {
super();
this.state = {
name:"STEPHEN LING",
}
}
render() {
const { name } = this.state;
return(
<Child fahterName={name}/>
)
}
}
- 子组件- Child Component
import { Component, Fragment } from "react";
import PropTypes from "prop-types";
export default class Child extends Component {
constructor() {
super();
this.props = {
fatherName:PropTypes.string.isRequired,
}
this.state = {
name:"stephen ling"
}
}
onChangeFatherName = () => {
const { onChangeFatherName } = this.props;
onChangeFatherName();
}
render() {
const { fatherName } = this.props;
const { name } = this.state;
return(
<Fragment>
<h1>我的父亲:{fatherName},我:{name}</h1>
<button onClick={this.onChangeFatherName}>给我父亲改个名字</button>
</Fragment>
)
}
}
总结: 将父组件的值直接通过props传入子组件,子组件直接使用该值即可。
子向父传值
子向父传值也同时非常常见。
1.由子组件的事件触发,在触发的函数体中调用父组件传入的方法,将子组件里的值传入即可。
- 父组件
import { Component, Fragment } from "react";
export default class Father extends Component {
constructor() {
super();
this.state = {
name:"STEPHEN LING",
};
};
changeMyName = newName => {
this.setState({
name: newName,
});
};
render() {
const { name } = this.state;
return(
<Fragment>
<h1>{this.state.name}</h1>
<Child onChangeFatherName={this.changeMyName}/>
</Fragment>
)
}
}
- 子组件
import { Component, Fragment } from "react";
import { Button, Input } from "antd";
export default class Child extends Component {
handleChange = value => {
this.setState({
name:e.target.value,
});
};
onChangeFatherName = () => {
const { onChangeFatherName } = this.props;
onChangeFatherName(this.state.name);
};
render() {
const { fatherName } = this.props;
const { name } = this.state;
return(
<Fragment>
<Input htmlype="text" placeholder="请输入父亲的名字." value={this.state.name} onChange={this.handleChange}/>
<Button onClick={this.onChangeFatherName}>给我父亲改个名字</button>
</Fragment>
)
}
}
总结: 将父组件的改变状态的方法传入子组件的props,绑定给子组件中的某些触发事件譬如按钮的点击,输入框输入等等,得到子组件的值或状态或动作再调用父组件的方法得到子组件中的值。
兄弟间传值
兄弟间传值由于没有任何嵌套关系,所以结合上述两种情况,很容易想到将需要共享的值和方法使用上述的方法传至共同的父组件,由父组件再传入。
建议使用react-redux或者dva框架,了解不多,刚刚研究。
dva 方式
- 兄弟组件1
import { Component, Fragment } from "react";
import { Connect } from 'dva';
@connect(({ name })=>({
name,
}))
export default export default class Bro1 extends Component {
constructor() {
super();
};
handleChange = e => {
const { dispatch } = this.props;
dispatch({
type:"name/updateBro2Name",
payload:e.target.value,
});
};
render(){
const { name:{ bro1, bro2 } } = this.props;
return(
<Fragment>
<h1>{bro1}</h1>
<Input value={bro2} onChange={this.handleChange}/>
</Fragment>
)
}
};
- 兄弟组件2
import { Component, Fragment } from "react";
import { Connect } from 'dva';
@connect(({ name })=>({
name,
}))
export default class Bro2 extends Component {
constructor() {
super();
};
handleChange = e => {
const { dispatch } = this.props;
dispatch({
type:"name/updateBro1Name",
payload:e.target.value,
});
};
render(){
const { name:{ bro1, bro2 } } = this.props;
return(
<Fragment>
<h1>{bro2}</h1>
<Input value={bro1} onChange={this.handleChange}/>
</Fragment>
)
}
};
- 共同的父组件
import { Component, Fragment } from "react";
import { Connect } from "dva";
@Connect(({ name })=>({
name,
}))
export default class Father extends Component {
render{
const { name:{ bro1, bro2 } } = this.props;
return (
<Fragment>
<Bro1/>
<Bro2/>
</Fragment>
)
}
};
- name.js 放置两个兄弟组件的共同状态
export default {
namespace: "name",
state : {
bro1: "",
bro2: "",
};
reducers: {
updateBro1Name(state,action){
return {
...state,
bro1 : action.payload,
}
};
updateBro2Name(state,action){
return {
...state,
bro2 : action.payload,
}
};
};
};
总结: 事实上是将一些共同的状态存入一个更高的组件中存放着,从这个地方操作值和调用值。