React 基础笔记 04

207 阅读3分钟

React 基础笔记 04

React Hooks

使用 hooks 的理由

  • 高阶组件为了复用,导致代码层级复杂
  • 生命周期复杂
  • 写成 function 组件,无状态组件

useState (保存组件状态)

const [name,setName] = useState('smiling')

useEffct (处理副作用) 和 useLayoutEffect (同步执行副作用)

区别:useLayoutEffect 在 React 完成 DOM 更新后马上同步调用的代码,会阻塞页面渲染;useEffct 是在整个页面渲染完才会调用的代码。

函数组件中不存在生命周期。

  1. useEffct 传空数组,useEffct 内部,函数体里面只执行一次
import React, { useEffect, useState } from "react";

function App() {
  const [name, setName] = useState('smiling')
  
  useEffect(()=>{
    console.log(name)
  },[])
  
  return (<>
    <div>{name}</div>
  </>);
}

export default App;
  1. useEffct 传值,当值发生改变,useEffct 内部,函数体里面只执行
import React, { useEffect, useState } from "react";

function App() {
  const [name, setName] = useState('smiling')
  
  // 点击按钮修改 name
  const onclick = () => {
    setName('wangling')
  }
  
  // 当 name 改变将首字母大写
  useEffect(()=>{
    const str = name.substring(0,1).toUpperCase() + name.substring(1)
    setName(str)
  },[name])
  
  return (<>
    <div>{name}</div>
    <button onClick={onclick}>修改名字</button>
  </>);
}

export default App;

useCallback (记忆函数)

防止因为组件重新渲染,导致方法被重新创建,起到缓存作用;只有第二个参数变化了,才重新声明一次。

function App() {
  const [name, setName] = useState('smiling')

  const onclick = useCallback(()=>{
    console.log(name)
  },[name])

  return (<>
    <div>{name}</div>
    <button onClick={onclick}>查看</button>
  </>);
}

export default App;

useMemo (记忆组件)

useCallback 的功能完全可以由 useMemo 取代,如果想使用 useMemo 返回一个记忆函数也是可以的。

区别: useCallback 不会执行第一个参数函数,而是返回一个函数,useMemo 会执行第一个函数并且将函数执行的结果返回。 因此,useCallback 常用于记忆事件函数,生成记忆后事件函数传递给子组件使用。useMemo 更适合经过函数计算得到的一个确定的值。

useRef (保存引用值)

function App() {
  const mytext = useRef() // React.createRef()
  const handChange = (e) => {
    console.log(e.target.value) // 获取输入框的值
  }
  return (<>
    <input ref={mytext} onChange={handChange} />
  </>);
}

export default App;

useReducer 和 useContext (减少组件层级)

useContext 可以跨越组件层级直接传递变量,实现数据共享。

useContext 和 redux 的区别: useContext : 用于解决组件之间传值的问题; redux : 统一管理应用状态。 可以使用 useContext 结合 useReducer 模拟一个小型的 redux 场景。

import React, { useState, createContext, useContext } from "react";
const CountContext = createContext(0); // 创建 Context

const App = () => {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>父组件点击数量:{count}</p>
      <button onClick={() => setCount(count + 1)}>{"点击+1"}</button>
      // CountContext.Provider 包裹需要接收参数的子组件,并通过 value  传值
      <CountContext.Provider value={count}>
        <Counter />
      </CountContext.Provider>
    </div>
  );
};

const Counter = () => {
  // 子组件通过 useContext 把刚刚创建好的 CountContext 作为参数传进去,并读取 count 值
  const count = useContext(CountContext);
  return <p>子组件获得的点击数量:{count}</p>;
};

export default App;

useReducer : 是 React 提供的一个高级 Hook,可以使我们的代码又更好的可读性、可维护性、可预测性。 reducer 是一个函数 (state, action) => {} 接受当前应用的 state 和 触发的动作 action, 计算并返回最新的 state。

import React, { useReducer } from "react";


const App = () => {
  // 执行的操作
  const reducer = (preState,action) =>{
    const newState = {...preState}
    switch(action.type){
      case 'add': 
      newState.cont ++
        return newState
      case 'minus': 
      newState.cont --
        return newState
    }
  }
  // 初始化状态
  const initalState = {
      cont: 0,
  }

  const [state, dispatch] = useReducer(reducer,initalState)
  return (
    <div>
      <button onClick={()=>{
        dispatch({
          type: 'minus'
        })
      }}>-</button>
      {state.cont}
      <button onClick={()=>{
        dispatch({
          type: 'add'
        })
      }}>+</button>
    </div>
  );
};

自定义 hooks

自定义 hooks 实际上就是把每个组件中重复的逻辑单独抽离出来,然后封装成函数。必须使用 use 开头,不然使用不了一些 hooks


  • @Title: React 基础笔记 04
  • @Content: React
  • @Autor: ling.wang
  • @StudyDate: 2022-07-06
  • @WritingDate: 2022-07-06