深切明白react

近来在看react源码,觉察之前对react的明白着实浅薄,这里记录了一些之前忽视的点。

createElement和component

在react内里,经由babel的剖析后,jsx会变成createElement实行后的效果。

const Test = (props) => <h1>hello, {props.name}</h1>;
<Test name="world" />

<Test name="world" />经由babel剖析后会变成createElement(Test, {name: “world}),这里的Test就是上面的Test要领,name就是Test要领内里接收的props中的name。
现实受骗我们从最先加载到衬着的时刻做了下面几步:

// 1. babel剖析jsx
<Test name="world"> -> createElement(Test, {name: "world"})
// 2. 对函数组件和class组件举行处置惩罚
// 假如是类组件,不做处置惩罚,假如是函数组件,增添render要领
const props = {name: world};
const newTest = new Component(props);
newTest.render = function() {
    return Test(props);
}
// 3. 实行render要领
newTest.render();

key

react中的diff会依据子组件的key来对照前后两次virtual dom(纵然前后两次子组件递次打乱),所以这里的key最好运用不会变化的值,比方id之类的,最好别用index,假如有两个子组件互换了位置,那末index就会致使diff悉数失效。

cloneElement

本来对cloneElement的明白就是相似cloneElement(App, {})这类写法,如今看了完成以后才明白。本来第一个参数应该是一个reactElement,而不是一个reactComponent,应该是<App />,而不是App,这个也确实是我没有好好看文档。

setState

react内里setState后不会马上更新,但在某些场景下也会马上更新,下面这几种状况打印的值你都能回复的上来吗?

class App extends React.Component {
    state = {
        count: 0;
    }
    test() {
        this.setState({
            count: this.state.count + 1
        }); 
        console.log(this.state.count); // 此时为0
        this.setState({
            count: this.state.count + 1
        });
        console.log(this.state.count); // 此时为0
    }
    test2() {
        setTimeout(() => {
            this.setState({
                count: this.state.count + 1
            });
            console.log(this.state.count); // 此时为1
            this.setState({
                count: this.state.count + 1
            });
            console.log(this.state.count); // 此时为2
        })
    }
    test3() {
        Promise.resolve().then(() => {
            this.setState({
                count: this.state.count + 1
            });
            console.log(this.state.count); // 此时为1
            this.setState({
                count: this.state.count + 1
            });
            console.log(this.state.count); // 此时为2
        })
    }
    test4() {
        this.setState(prevState => {
            console.log(prevState.count); // 0
        return {
            count: prevState.count + 1
        };
        });
        this.setState(prevState => {
            console.log(prevState.count); // 1
            return {
                count: prevState.count + 1
            };
        });
    }
    async test4() {
        await 0;
        this.setState({
            count: this.state.count + 1
        });
        console.log(this.state.count); // 此时为1
        this.setState({
            count: this.state.count + 1
        });
        console.log(this.state.count); // 此时为2
    }
}

在react中为了防备屡次setState致使屡次衬着带来不必要的机能开支,所以会将待更新的state放到行列中,比及适宜的机遇(平常是组件第一次衬着或触发事宜后)后举行batchUpdate,所以在setState后没法马上拿到更新后的state,很多人说setState是异步的,setState表现确实是异步,只是内里没有用异步代码完成。
假如是给setState传入一个函数,这个函数是实行前一个setState后才被挪用的,所以函数返回的参数能够拿到更新后的state。
然则假如将setState在异步要领中(setTimeout、Promise等等)挪用,因为要领是异步的,会致使组件pending完毕后才实行异步要领中的setState,这个时刻因为组件已不处于pending状况了,会致使setState马上实行,这时候经由过程this.state能够拿到最新的值。

ref

ref用到原生的标签上,能够直接在组件内部用this.refs.xxx的要领获取到实在DOM。
ref用到组件上,需要用ReactDOM.findDOMNode(this.refs.xxx)的体式格局来获取到这个组件对应的DOM节点。

shouldComponentUpdate

当shouldComponentUpdate返回false的时刻,组件没有从新衬着,然则更新后的state和props已挂载到了组件上面,这个时刻假如打印state和props,会发明拿到的已是更新后的了。

    原文作者:尹光耀
    原文地址: https://segmentfault.com/a/1190000017242270
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞