
父子组件的通信
- 1.父 => 子
父组件向子组件的通信是通过props。较为简单,代码如下
class Child_1 extends React.Component {
constructor(...arg) {
super(...arg)
}
render() {
return <div>{this.props.data}</div>
}
}
class Parent extends React.Component{
constructor(...arg){
super(...arg)
}
render(){
return <Child_1 data="the data from Parent"/>
}
}
ReactDOM.render(<Parent />,document.getElementById('app'));
如果父组件与子组件之间不止一个层级,如 Parent 与 Child_1_1 这样的关系,可通过 ... 运算符(Object 剩余和展开属性),将父组件的信息,以更简洁的方式传递给更深层级的子组件。通过这种方式,不用考虑性能的问题,通过 babel 转义后的 ... 运算符 性能和原生的一致,且上级组件 props 与 state 的改变,会导致组件本身及其子组件的生命周期改变
// 再通过在使用后辈组件时,将props作为数据向后传递
class Child_1_1 extends React.Component {
render() {
return <p>孙:{this.props.msg}</p>
}
}
class Child_1 extends React.Component {
constructor(...arg) {
super(...arg)
}
render() {
return <div>
<div>子:{this.props.data}</div>
<Child_1_1 msg={this.props.data} />
</div>
}
}
class Parent extends React.Component {
constructor(...arg) {
super(...arg)
}
render() {
return <Child_1 data="the data from Parent"/>
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'));
- 2.子 => 父
子组件向父组件通讯,同样也需要父组件向子组件传递 props 进行通讯,只是父组件传递的,是作用域为父组件自身的函数,子组件调用该函数,将子组件想要传递的信息,作为参数,传递到父组件的作用域中。
// 代码一 有bug
class Child extends React.Component {
constructor(...args) {
super(...args);
this.state = {
data: 'the data from child'
}
}
static getDerivedStateFromProps(nextProps,preState) {
nextProps.fn(preState.data)
}
render() {
// this.props.fn(this.state.data);
return <div>Child:{this.state.data}</div>
}
}
class Parent extends React.Component {
constructor(...args) {
super(...args);
this.state = {
getData: ''
}
}
fn(data) {
console.log('子组件调用了fn方法!');
this.setState({
getData: data
})
}
render() {
return (
<div>
<Child fn={this.fn.bind(this)}/>
<div>Parent:{this.state.getData}</div>
</div>)
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'));
(此处报错ReferenceError: state is not defined 已解决。原因:在constructor中的state应该是this.state={}。在constructor外的state可以直接state = {})
(此时又报错Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.原因:子组件改变了父组件的state,触发了父组件的re-render,导致父组件重新渲染,此时渲染到了子组件,子组件再次调用函数改变父组件state,又重新触发re-render,造成死循环。解决方法:在父组件的setState外加判断,当this.state.getDate和调用时的data相同时不执行setState避免重复设置状态)
// 代码二
class Child extends React.Component {
constructor(...args) {
super(...args);
this.state = {
data: 'the data from child'
}
}
static getDerivedStateFromProps(nextProps, preState) {
nextProps.fn(preState.data)
}
render() {
return <div>Child:{this.state.data}</div>
}
}
class Parent extends React.Component {
constructor(...args) {
super(...args);
this.state = {
getData: ''
}
}
fn(data) {
if (this.state.getData !== data) {
this.setState({
getData: data
})
}
}
render() {
return (
<div>
<Child fn={this.fn.bind(this)}/>
<div>Parent:{this.state.getData}</div>
</div>)
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'));
上下两段代码中,无论在render还是getDerivedStateFromProps阶段执行fn结果都是一样的。附上本项目启动后的生命周期
【死循环的另一种常见情况】
只要进入了某一个阶段,则这个阶段的生命周期都会做。
所以在Updaing整个阶段中,5个生命周期:componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate中,都不能操作state!如果操作了state,再次导致更新,所有生命周期再次执行,导致死循环 。
兄弟组件的通信
- 1.利用父组件实现兄弟组件间的通信
这种方法相对简单,C1通过调用父组件的函数向父组件传递数据,父组件得到数据后再通过props传递给C2
// 利用父组件实现兄弟组件的通信
class Child1 extends React.Component {
constructor(...args) {
super(...args)
this.state = {
msg: 'the message form child-1'
}
}
render() {
this.props.fn(this.state.msg)
return (
<div>
Child-1:{this.state.msg}
</div>
)
}
}
class Parent extends React.Component {
constructor(...args) {
super(...args)
this.state = {
data: ''
}
}
fn(msg) {
if (msg !== this.state.data) {
this.setState({
data: msg
})
}
}
render() {
return (
<div>
<Child1 fn={this.fn.bind(this)}/>
Parent:{this.state.data}
<Child2 msg={this.state.data}/>
</div>
)
}
}
class Child2 extends React.Component {
constructor(...args) {
super(...args)
}
render() {
return (
<div>
Child-2:{this.props.msg}
</div>
)
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'));
然而,这个方法有一个问题,由于 Parent 的 state 发生变化,会触发 Parent 及从属于 Parent 的子组件的生命周期,所以我们在控制台中可以看到,在各个组件中的 componentDidUpdate 方法均被触发。