
父子組件的通信
- 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'));
如果父組件與子組件之間不止一個(gè)層級,如 Parent 與 Child_1_1 這樣的關(guān)系,可通過 ... 運(yùn)算符(Object 剩余和展開屬性),將父組件的信息,以更簡潔的方式傳遞給更深層級的子組件。通過這種方式,不用考慮性能的問題,通過 babel 轉(zhuǎn)義后的 ... 運(yùn)算符 性能和原生的一致,且上級組件 props 與 state 的改變,會導(dǎo)致組件本身及其子組件的生命周期改變
// 再通過在使用后輩組件時(shí),將props作為數(shù)據(jù)向后傳遞
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 進(jìn)行通訊,只是父組件傳遞的,是作用域?yàn)楦附M件自身的函數(shù),子組件調(diào)用該函數(shù),將子組件想要傳遞的信息,作為參數(shù),傳遞到父組件的作用域中。
// 代碼一 有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('子組件調(diào)用了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'));
(此處報(bào)錯(cuò)ReferenceError: state is not defined 已解決。原因:在constructor中的state應(yīng)該是this.state={}。在constructor外的state可以直接state = {})
(此時(shí)又報(bào)錯(cuò)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,觸發(fā)了父組件的re-render,導(dǎo)致父組件重新渲染,此時(shí)渲染到了子組件,子組件再次調(diào)用函數(shù)改變父組件state,又重新觸發(fā)re-render,造成死循環(huán)。解決方法:在父組件的setState外加判斷,當(dāng)this.state.getDate和調(diào)用時(shí)的data相同時(shí)不執(zhí)行setState避免重復(fù)設(shè)置狀態(tài))
// 代碼二
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階段執(zhí)行fn結(jié)果都是一樣的。附上本項(xiàng)目啟動后的生命周期
【死循環(huán)的另一種常見情況】
只要進(jìn)入了某一個(gè)階段,則這個(gè)階段的生命周期都會做。
所以在Updaing整個(gè)階段中,5個(gè)生命周期:componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate中,都不能操作state!如果操作了state,再次導(dǎo)致更新,所有生命周期再次執(zhí)行,導(dǎo)致死循環(huán) 。
兄弟組件的通信
- 1.利用父組件實(shí)現(xiàn)兄弟組件間的通信
這種方法相對簡單,C1通過調(diào)用父組件的函數(shù)向父組件傳遞數(shù)據(jù),父組件得到數(shù)據(jù)后再通過props傳遞給C2
// 利用父組件實(shí)現(xiàn)兄弟組件的通信
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'));
然而,這個(gè)方法有一個(gè)問題,由于 Parent 的 state 發(fā)生變化,會觸發(fā) Parent 及從屬于 Parent 的子組件的生命周期,所以我們在控制臺中可以看到,在各個(gè)組件中的 componentDidUpdate 方法均被觸發(fā)。