react嵌套组件的构建顺序测试题

156 阅读2分钟

1.点击Father组件的div,Child会打印Child吗

function Child() {
  console.log('Child');
  return <div>Child</div>;
}
function Father(props) {
  const [num, setNum] = React.useState(0);
  return (
    <div onClick={() => {setNum(num + 1)}}>
      {num}
      {props.children}
    </div>
  );
}
function App() {
  return (
    <Father>
      <Child/>
    </Father>
  );
}
const rootEl = document.querySelector("#root");
ReactDOM.render(<App/>, rootEl);

2 挂载完成和状态的更新时,是父组件先更新还是子组件先更新? 下列代码打印顺序是什么

function Child() {
  useEffect(() => {
    console.log('Child');
  }, [])
  return <h1>child</h1>;
}
    
function Father() {
  useEffect(() => {
    console.log('Father');
  }, [])
      
  return <Child/>;
}
    
function App() {
  useEffect(() => {
    console.log('App');
  }, [])
    
  return <Father/>;
}

3 在嵌套组件中,是父组件先构建,还是子组件先构建?

import React, { useEffect } from 'react';
function Child() {
  console.log('Child');
  return <h1>child</h1>;
}

function Father() {
  console.log('Father');
  return <Child />;
}

function App() {
  console.log('App');
  return <Father />;
}

export default App;

``

4 setState是异步执行吗?

import React, { useState } from 'react';
export default function StateDemo() {
  const [num, setNum] = useState(1);

  const onBtnClick = (e) => {
    setNum((num) => {
      console.log('num', num);
      return num + 1;
    });
    foo();
  };

  const foo = () => {
    new Promise((resolve) => {
      setTimeout(() => {
        resolve();
      }, 1000);
    }).then(() => {
      print();
    });
  };

  const print = () => {
    console.log(num); // 1
  };
  return <button onClick={onBtnClick}>click me</button>;

5 能及时拿到更新后的state数据吗

  class App extends Component {
    state = { num: 0 }
    onBtnClick = () => {
      this.setState({ num: this.state.num + 1 })
      console.log(this.state.num)
    }
    
    render() {
      return (
        <button onClick={this.onBtnClick}>
          click me
        </button>
      )
    }
  } 

6 函数组件中 能及时拿到更新后的state数据吗

import React, { useState } from 'react';
import { Button, Space } from 'antd';

export default () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
    console.log(`更新后的值:`, count);
  };
  return (
    <Space>
      <span style={{ fontSize: 30, color: 'red' }}>{count}</span>
      <Button
        type="primary"
        onClick={() => {
          handleClick();
        }}
      >
        加1
      </Button>
    </Space>
  );
};

7 打印结果是什么

  import React, { useState } from 'react';
import { Button, Space } from 'antd';

export default () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount((count) => {
      // 使用箭头函数 并将count 返回
      count++;
      console.log(`立即更新后的值:`, count);
      return count;
    });
  };
  return (
    <Space>
      <span style={{ fontSize: 30, color: 'red' }}>{count}</span>
      <Button
        type="primary"
        onClick={() => {
          handleClick();
        }}
      >
        加1
      </Button>
    </Space>
  );
};

8 setSTate 异步操作

import React, { Component } from 'react';

export default class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      name: '今天是七夕节'
    };
    this.handleClick = this.handleClick.bind(this)
  }

  async handleClick() {
    await this.setState({
      name: '跟你这只单身狗有什么关系'
    })
    console.log(this.state.name)
  }
  
  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
        <button onClick={this.handleClick}>点击查看</button>
      </div>
    )
  }
}

export default App;

结果拿不准?在stackblitz.com/edit/react-… 测试一下你的答案!

最后总结

  1. React组件的构建和开始挂载是从根元素到子元素的,因此数据流是从上到下的,挂载完成和状态的更新是从子元素到根元素,此时可以将最新状态传给根元素

  2. 组件和DOM元素的一个区别是,DOM元素会在当前位置创建,而React组件的构建渲染具有层级顺序

  3. 在类组件中,使用await 搭配 this.setState一起使用,可以在setState之后的下一个 await 获取到最新的值。但是在函数组件中,使用await无效,不能获取到最新的值。