十分钟速成React Hook,适用于新手~

532 阅读4分钟

前言

10分钟快速过完react中的hook函数,适用于新手,大家可以用npm create vite快速搭建一个react本地环境,在本地跑下代码体验更佳,如果对您有一点帮助,麻烦点个赞哦~

useState

声明一个变量和改变当前变量值的方法

const [state, setState] = useState(null);

例子:

const [userName, setUserName] = useState('小明');
const click = (name) => {
    setUserName(name)//小明变为小白
}
return (
    <>
        <h3>{userName}</h3>
        <button onClick={()=>click('小白')}>改变名称</button>
    </>  
)

注:useState是异步操作

useRef

useRef以同步的方式设置值并返回current对象

inputEl.current可拿到声明值并设置,下面挂载到标签中即可以拿到标签属性

const App = ()=>{
  const inputEl = useRef(null);
  const name = useRef('小明');
  const click = () => {
    console.log(name.current);//没有挂载到标签中输出小明
    inputEl.current.focus();//获取标签属性设置焦点
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={click}>获取焦点</button>
    </>
  );
}

注:useRef是同步操作

useEffect

创造react生命周期

挂载时

useEffect(()=>{
    //挂载时执行的回调
},[])

更新时

const [num,setNum] = useState(0);
useEffect(()=>{
    console.log(num) //num变化的时候会触发当前回调
},[num])
​
return (
    <>
        <h3>{num}</h3>
        <button onClick={()=>setNum(num+1)}>增加次数</button>
    </>  
)

销毁时

函数中返回一个函数(高阶函数)

useEffect(()=>{
    //这里执行挂载阶段
    return ()=>{
        console.log('离开页面时执行销毁阶段')
    }
},[])

注:useEffct同步的,不能用async声明执行异步操作

useContext

作用:根组件数据共享给子组件

使用createContext创建上下文

通过声明上下文AppComponent.provider挂载组件并传入value

import React, { createContext, useContext, useState } from 'react'
// 创造一个上下文
const AppComponent = createContext(null);
//父组件
const Father = () => {
  const {age} = useContext(AppComponent)//接收父组件传入的值
  return(
    <div>
      父年龄:{age}
      <Child></Child>
    </div>
  )
}
//子组件
const Child = () => {
  const {age,setAge} = useContext(AppComponent)//接收上下文(根组件)传入的值和方法
  return(
    <div>
      子年龄:{age}
      <button onClick={()=>{setAge(age+1)}}>年龄+1</button>
    </div>
  )
}
//根组件
const App = () => {
  const [age,setAge] = useState(0)
  return(
    // 指定上下文使用范围,使用provider传入值和方法给子组件共享使用
    <AppComponent.Provider value={{age,setAge}}>
      <Father></Father>
    </AppComponent.Provider>
  )
}
export default App

useReducer

作用:在useState的基础上加入更多的逻辑

const App = ()=>{
  const [ number , setNumbner ] = useReducer((state,action)=>{
      const { name  } = action
      /* 根据不同名称修改state值 */
      switch(name){
          case 'add':
              return state + 1
          case 'sub':
              return state - 1 
          case 'reset':
              return 0       
      }
      return state
  },0)
  return <div>
      当前值:{ number }
      <button onClick={()=>setNumbner({ name:'add' })} >增加</button>
      <button onClick={()=>setNumbner({ name:'sub' })} >减少</button>
      <button onClick={()=>setNumbner({ name:'reset'})} >重置</button>
  </div>
}

useMemo

作用:提高性能,当依赖的值不变则不会重复渲染,如果依赖值变则再次渲染。useMemo 返回的是函数运行的结果。

用法:声明后直接调用

const App = ()=>{
  const [num,setNum] = useState(0)
  const CountCallback = useMemo(() => {
      return num + 10
  },[num]);//CountCallback返回计算的总数
  return <div>
      {CountCallback}
      <button onClick={()=>{setNum(num+1);}} >设置值+1</button>
  </div>
}

memo

作用:防止当前引入组件重复渲染

const App = ()=>{
  const [num,setNum] = useState(0)
  const CountCallback = useMemo(() => {
      return num + 10
  },[num]);//CountCallback返回计算的总数
  return <div>
      {CountCallback}
      <button onClick={()=>{setNum(num+1);}} >设置值+1</button>
  </div>
}
export default memo(App);

useCallback

作用:提高性能,用于函数,防止函数重复渲染,useCallback 返回的是函数。

用法:声明后函数调用

const App = ()=>{
  const [num,setNum] = useState(0)
  const CountCallback = useCallback(() => {
      return num + 10
  },[num]);//CountCallback返回计算的总数
  return <div>
      {CountCallback()}
      <button onClick={()=>{setNum(num+1);}} >设置值+1</button>
  </div>
}

两者区别:在于 useMemo 返回的是函数运行的结果, useCallback 返回的是函数

forwardRef

作用:forwardRef会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中,通常配合useImperativeHandle使用,示例结合了useImperativeHandle看下面

useImperativeHandle

配合forwardRef使用,共用ref的值

  1. 第一个参数:接受 forWardRef 传递过来的 ref
  2. 第二个参数:处理函数,返回值作为暴露给父组件的ref对象。
  3. 第三个参数:依赖项 deps,依赖项更改形成新的ref对象。

结合示例

const Child = forwardRef((props, ref) =>{
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();//获取焦点
    },
    clear: ()=>{
      inputRef.current.value = ''//清空数据
    }
  }));
  return <input ref={inputRef}  />;
})
​
const App = ()=>{
  const ref = useRef(null)
  return (
    <>
      <Child ref={ref}></Child>
      <button onClick={()=>{ref.current.focus()}}>获取焦点</button>
      <button onClick={()=>{ref.current.clear()}}>清除数据</button>
    </>
  )
}

useLayoutEffect

同步执行的useEffect

用法与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新。

尽可能使用标准的 useEffect 以避免阻塞视觉更新。

useDebugValue

useDebugValue 可用于在 React 开发者工具中显示自定义 hook 的标签。

// 自定义 Hook
const useMyCount = (num) => {
  const [ count, setCount ] = useState(0);
​
  // 延迟格式化
  useDebugValue(count > num ? '溢出' : '不足', status => {
    return status === '溢出' ? 1 : 0;
  });
​
  const myCount = () => {
    setCount(count + 1);
  }
​
  return [ count, myCount ];
}
​
const App = ()=>{
  const [ count, seCount ] = useMyCount(10);
  return (
    <div>
      {count}
      <button onClick={() => seCount()}>setCount</button>
    </div>
  )
}

提示:React官网不推荐你向每个自定义 Hook 使用 useDebugValue,只有自定义 Hook 被复用时才最有意义。

结语

如果你觉得此文对你有一丁点帮助,麻烦点个赞哈,谢谢大家~