React學(xué)習(xí)筆記(三)-組件通信

層級.png

父子組件的通信

  • 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)目啟動后的生命周期


life.PNG

【死循環(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ā)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容