【面试 · 三】react大集合(类式/函数式)

目录

类式组件生命周期

函数式组件hook

组件通信

类组件和函数组件的区别

全局状态管理react-redux

路由

受控组件和非受控组件

高阶组件

Fiber

类式组件生命周期

constructor

初始化组件的状态和绑定事件处理器。

constructor(props) {
  super(props);
  this.state = { count: 0 };
  this.handleClick = this.handleClick.bind(this); // 绑定事件处理器
}

getDerivedStateFromProps

用于在挂载和更新前根据 props 更新 state。

static getDerivedStateFromProps(nextProps, prevState) {
  if (nextProps.value !== prevState.value) {
    return { value: nextProps.value };
  }
  return null;
}

render

必须实现的方法,渲染组件的虚拟 DOM。

componentDidMount

组件挂载完成后调用,通常用于发起网络请求、订阅事件等副作用操作。

componentDidMount() {
  fetch('/api/data').then(response => this.setState({ data: response.data }));
}

shouldComponentUpdate

判断组件是否需要重新渲染。返回 false 可以阻止不必要的重新渲染。

shouldComponentUpdate(nextProps, nextState) {
  return nextState.count !== this.state.count;
}

getSnapshotBeforeUpdate

在最新的渲染输出提交给 DOM 之前调用,可以捕获一些 DOM 信息(如滚动位置),以便在 componentDidUpdate 中使用。

getSnapshotBeforeUpdate(prevProps, prevState) {
  if (prevProps.items.length < this.props.items.length) {
    return this.listRef.scrollHeight;
  }
  return null;
}

componentDidUpdate

组件更新完成后调用,可以在此进行副作用操作(如网络请求、DOM 操作等)

可以调用 setState(),但必须包裹在条件语句中,否则会导致无限循环

componentDidUpdate(prevProps, prevState, snapshot) {

}

componentWillUnmount

组件卸载和销毁之前调用,通常用于清理工作,如取消请求、清除定时器、移除监听器等。

componentWillUnmount() {
  clearInterval(this.timerID);
  this.subscription.remove();
}

错误边界

 static getDerivedStateFromError(error) {  
    // 更新 state 以触发备用 UI 的渲染  
    return { hasError: true };  
 }  
  
 componentDidCatch(error, errorInfo) {  
    // 你可以将错误日志上报给服务器  
    console.error("Uncaught error:", error, errorInfo);  
 }

函数式组件hook

useState

状态管理  返回一个状态值和更新函数

import React,{ useState } from 'react'
const [xxx, setXxx] = useState(  )

useEffect

组合了 componentDidMount, componentDidUpdate 和 componentWillUnmount 

useEffect(() => {
     在return上面可以执行任何带副作用操作
    return () => {  在组件卸载前执行
     在此做一些收尾工作, 比如清除定时器/取消订阅等
    }
}, [stateValue])  如果指定的是[], 回调函数只会在第一次render()后执行

useLayoutEffect

用于在浏览器重新绘制屏幕之前触发

useContext

订阅React上下文

const value = useContext(MyContext);
// 1. 创建上下文
const ThemeContext = createContext('light');
 
// 2. 提供上下文
const App = () => (
  <ThemeContext.Provider value="dark">
    <Child />
  </ThemeContext.Provider>
);
 
// 3. 使用上下文
const Child = () => {
  const theme = useContext(ThemeContext);
  return <div>Theme: {theme}</div>;
};

useRef

在函数组件中存储/查找组件内的标签或任意其它数据

const myRef = React.useRef()
 
function show(){
    alert(myRef.current.value)
}
 
<input type="text" ref={myRef}/>
<button onClick={show}>点我提示数据</button>

useMemo 和 useCallback

相当于 shouldComponentUpdate 的优化,用于避免不必要的计算和渲染

useMemo 和 useCallback

useReducer

useReducer (redux)

useReducer 是 React Hooks 中的一个函数,用于管理和更新组件的状态。它可以被视为 useState 的一种替代方案,适用于处理更复杂的状态逻辑。

相比于 useState,useReducer 在处理复杂状态逻辑时更有优势,因为它允许我们将状态更新的逻辑封装在 reducer 函数中,并根据不同的动作类型执行相应的逻辑。这样可以使代码更具可读性和可维护性,并且更容易进行状态追踪和调试。

import { useReducer } from 'react';

const initialState = {
  count: 0,
};

const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error('Unsupported action type');
  }
};

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  const increment = () => {
    dispatch({ type: 'increment' });
  };

  const decrement = () => {
    dispatch({ type: 'decrement' });
  };

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </div>
  );
}

组件通信

父传子

//类式组件————父
import React, { Component } from 'react'
import Son from './Son'

export default class Parent extends Component {
  state = {
    info: '我是父组件要传给子组件的数据!'
  }
  render() {
    const { info } = this.state
    return (
      <div >
        <h2>你好,我是Parent组件!</h2>
        {/* 父组件通过在子标签中添加 属性=值 将数据传递给子组件 */}
        <Son info={info} />
      </div>
    )
  }
}


//子
import React, { Component } from 'react'

export default class Son extends Component {
  render() {
    const { info } = this.props
    return (
      <div >
        <h2>你好,我是Son组件!</h2>
        <h3>我接受到父组件传递过来的数据是:{info}</h3>
      </div>
    )
  }
}

//函数式组件————父
import React from 'react'
import Son from './Son'

export default function Parent() {
  const info = '我是父组件要传给子组件的数据!'
  return (
    <div className='parent'>
      <h2>你好,我是Parent组件!</h2>
      {/* 父组件通过在子标签中添加 属性=值 将数据传递给子组件 */}
      <Son info={info} />
    </div>
  )
}


//子
import React from 'react'

export default function Son(props) {
  const {info} = props
  return (
    <div >
      <h2>你好,我是Son组件!</h2>
      <h3>我接受到父组件传递过来的数据是:{info}</h3>
    </div>
  )
}

子传父

//类式组件————父
import React, { Component } from 'react'
import Son from './Son'
import './index.css'

export default class Parent extends Component {
  state = {
    info: '我是父组件要传给子组件的数据!'
  }
  changeInfo = (info) => {
    this.setState({ info })
  }
  render() {
    const { info } = this.state
    return (
      <div className='parent'>
        <h2>你好,我是Parent组件!</h2>
        {/* 父组件给子组件绑定一个回调函数changeInfo */}
        <Son changeInfo={info => { this.changeInfo(info) }} />
        <h3>info信息是:{info}</h3>
      </div>
    )
  }
}



//子
import React, { Component } from 'react'

export default class Son extends Component {
  btnClick = () => {
    const info2 = '我是子组件改变之后传给父组件的数据!'
    this.props.changeInfo(info2 )
  }
  render() {

    return (
      <div className='son'>
        <h2>你好,我是Son组件!</h2>
        <button onClick={() => this.btnClick()}>点击改变父组件展示的info</button>
      </div>
    )
  }
}
//函数式组件————父
import React, { useState } from 'react'
import Son from './Son'
import './index.css'

export default function Parent() {
  const [info, setInfo] = useState('我是父组件要传给子组件的数据!')
  function changeInfo(info) {
    setInfo(info)
  }
  return (
    <div className='parent'>
      <h2>你好,我是Parent组件!</h2>
      {/* 父组件给子组件绑定一个回调函数changeInfo */}
      <Son changeInfo={info => changeInfo(info)} />
      <h3>info信息是:{info}</h3>
    </div>
  )
}



//子
import React from 'react'

export default function Son(props) {
  function btnClick() {
    const info2 = '我是子组件改变之后传给父组件的数据!'
    props.changeInfo(info2)
  }
  return (
    <div className='son'>
      <h2>你好,我是Son组件!</h2>
      <button onClick={btnClick}>点击改变父组件展示的info</button>
    </div>
  )
}

非父子通信 context

//类式组件————祖组件
import React, { Component } from 'react'
import Parent from './Parent'
import './index.css'

// 创建并暴露Context对象
export const { Provider, Consumer } = React.createContext()

export default class Grandpa extends Component {
  state = { username: 'aDiao', age: 20 }
  changeMessage = () => {
    this.setState({ username: '啊叼', age: 18 })
  }
  render() {
    const { username, age } = this.state
    return (
      <div className='grandpa'>
        <h3>我是祖组件</h3>
        <h4>我的用户名是:{username}</h4>
        <h4>我的年龄是:{age}</h4>
        <button onClick={this.changeMessage}>点我更改信息</button>
        <Provider value={{ username, age }}>
          <Parent />
        </Provider>
      </div>
    )
  }
}



//后代组件
import React, { Component } from 'react'
// 导入Grandpa组件中暴露出来的Context对象的Consumer
import { Consumer } from './Grandpa'

export default class Son extends Component {
  render() {
    return (
      <Consumer>
        {
          (value) => {
            return (<div className='son' >
              <h3>我是子组件</h3>
              <h4>我接收到的用户名是:{value.username}</h4>
              <h4>我接收到的年龄是:{value.age}</h4>
            </div >)
          }
        }
      </Consumer >

    )
  }
}

//函数式组件————祖组件
import React, { useState } from 'react'
import Parent from './Parent'
import './index.css'

export const { Provider, Consumer } = React.createContext()

export default function Grandpa() {
  const [user, setUser] = useState({ username: 'aDiao', age: 20 })
  function changeMessage() {
    setUser({
      username: '啊叼',
      age: 18
    })
  }
  return (
    <div className='grandpa'>
      <h3>我是祖组件</h3>
      <h4>我的用户名是:{user.username}</h4>
      <h4>我的年龄是:{user.age}</h4>
      <button onClick={changeMessage}>点我更改信息</button>
      <Provider value={user}>
        <Parent />
      </Provider>
    </div>
  )
}



//后代组件
import React from 'react'
import { Consumer } from './Grandpa'

export default function Son() {
  return (<div className='son' >
    <h3>我是子组件</h3>
    <h4>我接收到的用户名是:
      <Consumer>
        {value => {
          return `${value.username}`
        }}
      </Consumer>
    </h4>
    <h4>我接收到的年龄是:
      <Consumer>
        {value => {
          return `${value.age}`
        }}
      </Consumer></h4>
  </div >)
}

发布订阅 pubsub

消息订阅与发布

类组件和函数组件的区别

类组件和函数式组件的区别

全局状态管理react-redux

redux

路由

路由

路由传参

受控组件和非受控组件

受控组件和非受控组件

高阶组件

至少满足下面一个条件

       接受一个或者多个函数作为输入

       输出一个函数

高阶组件

Fiber

React Fiber算法是React 16中引入的新的diff算法。之前的diff算法(即Stack Reconciler)是递归调用,在处理大量子元素时会导致栈溢出。

Fiber算法基于虚拟DOM树来对真实DOM树进行增量渲染。它将虚拟DOM树拆分成多个Fiber节点,每个Fiber节点维护自己的状态和子树。

Fiber解析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值