React学习计划-react-hooks补充

React Hooks

1. 使用hooks理由

  1. 高阶组件为了复用,导致代码层级复杂
  2. 生命周期的复杂

2. useState(保存组件状态)

复制代码
const [state, setstate] = useState(initialState)

3. useEffect(处理副作用)和useLayoutEffect(同步执行副作用)

  1. 使用方式:

    useEffect(() => {
    // effect
    return () => {
    // cleanup
    };
    }[依赖的状态;空数组,表示不依赖])

  2. 说明:

  • 不传入依赖:对比componentDidMount生命周期,表示初始加载完后执行
  • 传入依赖:对比componentDidMountcomponentDidUpdate生命周期,表示加载完后和更新完成后执行
  • 回调函数内return函数,对比componentWillUnmount销毁生命周期
  1. 示例:

    useEffect(()=>{
    const timer = setInterval(()=>{
    console.log('这是定时器')
    }, 1000)
    return ()=>{
    console.log('componentWillUnmount销毁时触发')
    clearInterval(timer)
    }
    },[name])

  2. useEffectuseLayoutEffect区别:

简单来说就是调用时机不同,useLayoutEffect和原来componentDidMount & componentDidUpdate一致,在react完成DOM更新后马上同步调用代码,会阻塞页面渲染。useEffect则是在整个页面渲染完才会调用代码

官方优先建议使用useEffect

在实际使用时如果想避免页面抖动 (在useEffect里修改DOM很有可能出现)的话,可以把需要操作的DOM的代码放在useLayoutEffect里,在这里做DOM操作,这些DOM修改会和react做出的更改一起被一次性渲染到屏幕上,只有一次回流、重绘的代价

4. useCallBack(记忆函数)

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

复制代码
var handleClick = useCallback(()=>{
  console.log(name)
},[name])

<button onClick={()=>handleClick()}>点击</button>

// 只有name改变后,这个函数才会重新声明一次
// 如果传入空数组,那么就是第一次创建被缓存,如果name后期改变了,拿到的还是老name
// 如果传第二个参数,每次都会重新声明一次,拿到的就是最新的name

5. useMemo(记忆组件)(可以理解为Vue的计算属性)

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

复制代码
useCallback(fn, inputs) is equivalent to useMemo(()=> fn, inputs)

唯一的区别是:useCallback不会执行第一个参数函数,而是将它返回给你,而useMemo会执行第一个函数并将函数执行结果返回给你。所以在前面的例子中,可以返回handleClick来达到存储函数的目的。

所以useCallback常用记忆事件函数,生成记忆后的事件函数并传递给子组件使用。而useMemo更适合经过函数计算得到一个确定的值,比如记忆组件。

复制代码
const getFilterList = useMemo(
  ()=> list.filter(item => item.name.toUpperCase().includes(text.toUpperCase())),
  [list, text] // 如果list和text变化
  )

6. useRef(保存引用值)

  1. 设置ref属性值

    const myRef = useRef(null)
    <Child ref={myRef}/>

  2. 用于缓存一个变量值

    const [name, setName] = useState('zhangsan')
    var mycount = useRef(0)
    <button onClick={()=>{
    setName('lisi')
    mycount.current++
    }}>点击</button>
    {name}-{mycount}

7. useReduceruseContext(减少组件层级)

  1. useContext用于组件通信,接收父组件传入的值

    // 父组件
    import React from 'react'
    var GlobalContext = React.createContext()

    function App(){
    <GlobalContext.Provider value={{
    name: '张三',
    age: 20,
    changeAge: (value) => {
    setAge(value)
    }
    }}>
    <Child />
    </GlobalContext.Provider>
    }

    // 子组件内
    function Child(){
    const text = useContext(GlobalContext)
    }

  2. useReducer:实现Reduxreducer的功能,应用在组件通信中

    const reducer = (prevState, action)=>{
    const newState = { ...prevState }
    switch(action.type){
    case 'add':
    newState.count ++
    return newState
    case 'minus':
    newState.count --
    return newState
    default:
    return prevState
    }
    }
    const initialState = {
    count: 0
    }
    // FC中
    const [state, dispatch] = useReducer(reducer, initialState)

    <button onClick={()=>{
    dispatch({
    type: 'minus'
    })
    }}>-</button>
    {state.count}
    <button onClick={()=>{
    dispatch({
    type: 'add'
    })
    }}>+</button>

8. 自定义hooks

当我们想在两个函数之间共享逻辑时,我们会把它提取到第三个函数中。

必须以use开头吗?必须如此。这个约定非常重要。不遵循的话,由于无法判断某个函数是否包含其内部Hook的调用,React将无法自动检查你的Hook是否违反了Hook的规则

相关推荐
腾讯TNTWeb前端团队3 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰6 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪6 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪7 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy7 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom8 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom8 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom8 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom8 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom8 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试