1. 首页

react hook 初体验

定义:Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React。

作用: React Hooks 要解决的是状态共享问题,但是只共享数据的处理逻辑,不会共享数据本身。

一、优势

  1. 组件间复用状态逻辑复杂
  2. 难于理解的class

二、State Hook基础

useState 就是一个hook,它可以给组件添加内部state,它会返回一对值,当前状态和跟新它的函数。这个函数类似于class组件的this.setState 。 下面这个例子是最简单的计数器:


import React, { useState } from 'react' function Example() {   const [count, setCount] = useState(0)   return (     <div>       <button onClick={add}>点击+1</button>       <p>点击次数:{count}</p>     </div>   )   function add () {     setCount (count + 1)   } } export default Example

Image.png

三、Effect Hook

useEffect 默认情况下在每次更新之后都会执行,使用useEffect可以方便的访问state或其他props。 一个完整的effect的格式如下:


useEffect(() => {         effect         return () => {             cleanup         };     }, [input])

其中是effect是你需要执行的方法,return不是必须的,它返回的是一个清除机制。第二个参数[input]也不是必须的,指的是effect的依赖。如果第二个参数是[]表示的是仅在挂载和卸载的时候执行,不传表示在挂载和更新的时候执行。

四、Capture Value 特性

解释:每次 Render 的内容都会形成一个快照并保留下来,因此当状态变更而 Rerender 时,就形成了 N 个 Render 状态,而每个 Render 状态都拥有自己固定不变的 Props 与 State。什么是Cature Value 如下面一个例子: `


function Example() {   const [count, setCount] = useState(0) return (<div><button onClick={add}>点击测试</button></div>)   function add() {     setCount(5)     setTimeout(() => {       // 结果是0而不是5       console.log(count)     }, 1000)   } }

打印的结果是0,而不是5,开始很让人费解。根据Capture Value特性,第一次挂载组件的时候,count就已经形成了一份快照,并保留下来了。setTimeout里面操作的count就是最开始的快照。 另一个例子说明了这个问题:

function Example() {
    const [count, setCount] = useState(0);
    useEffect(() => {
        setTimeout(() => {
            console.log(`You clicked ${count} times`);
        }, 3000);
    });
    return (
        <div>
            <p>You clicked {count} times</p>
            <button onClick={() => setCount(count + 1)}>
                Click me
        </button>
        </div>
    );
}

Image [1].png

在快速点击按钮多下之后,上面结果说明每次更新都有一个快照保存了下来,每次打印出来的是对应的快照内容,而不是最后一次。接着你会想,我如何才能取到当前真正的值呢,而不是旧值。你需要使用useRef

function Example() {
    const [count, setCount] = useState(0);
    const latestCount = useRef(count);
    useEffect(() => {
      latestCount.current = count;
      setTimeout(() => {
        console.log(`You clicked ${latestCount.current} times`);
      }, 3000);
    });
    return(
    <div>Count: {count}
        <button  onClick={()=>{setCount(count+1)}} >点击我</button>
    </div>
    )
}

Image [2].png

useRef返回了一个ref对象,它是可变的,其current属性指向的当前内容,而不是之前的快照。

五、如何设置一个定时器

现在有这样一个需求,进入页面后,需要一个数字不断的加一,离开页面后清除这个定时器,又由于依赖了count,那么很容易想到下面这种写法:


function Example() {     const [count, setCount] = useState(0)     useEffect(() => {         let inter = setInterval(() => {             setCount(count + 1)             console.log('count-->', count)         }, 1000)         return () => {             console.log('stopInterval-->', count)             clearInterval(inter)         };     }, [count])     return (<div>         当前的值是:{count}     </div>) }

发现定时器能正常进行,并且页面可以显示数字:

Image [3].png

但是:为什么会不断的新建定时器后又销毁呢?这样实在是太不高效了。

Image [4].png

原来是因为useEffect依赖了count,当count改变后又反过来执行useEffect,其实setCount 还有函数回调方式,不用关心当前值。


function Example() {     const [count, setCount] = useState(0)     useEffect(() => {         let inter = setInterval(() => {             setCount(c => c + 1)         }, 1000)         return () => {             clearInterval(inter)               };     }, [])     return (<div>         当前的值是:{count}     </div>) } export default Example

六、useReducer

在上一节中,我们发现更新和动作耦合在一起,尤其在一个useEffect依赖多个变量时候。useReduceruseState的替代方案,它接收(state, action) => newState方法,它返回一个数组,类似于useState hook,第一个是当前状态,第二个是dispatch方法。


    const [state, dispatch] = useReducer(reducer, initialState, init)

利用useReducer可以重写最开始的加法器:


function Example() {     const [count, dispatch] = useReducer(reducer, 0)     function reducer (state, action) {         return action.type === 'add' ? state + 1 :state - 1     }     return (<div>         <button onClick={() => {dispatch({type: 'add'})}}>+1</button>         <button onClick={() => {dispatch({type: 'decrement'})}}>-1</button>         当前的值是:{count}     </div>) }

Image [5].png

七、其他hooks

查看官方文档 自定义Hook其他Hook

八、使用自定义Hook封装axios

  1. 首先利用自定义Hooks 实现一个fetchApi,传入一个axios和参数params,返回结果data

function useFetch(fetch, params) {     const [data, setData] = useState({});     const fetchApi = useCallback(async () => {         const res = await fetch(params);         if (res.code === 1) {             setData(res.data);         }     }, [fetch, params]);     useEffect(() => {         fetchApi();     }, [fetchApi]);     return data; }

提供一个axios方法fetch


export const fetch = params => {     const url = 'baseUrl' + (params);     return axios(url).then(res => res.json()); };

去使用这个useFetch


function Demo() {     const data = useFetch(fetch, { params1: "xxx" }     return <div>得到返回值:{data}</div>; }

结果发现,这样并不行得通,一下子程序就会陷入死循环,好好分析一下,原来params是一个对象,usecallback会误认为每次params都改变了,导致陷入了一个死循环中。:render –>useEffect–>useCllback—>data改变—>render,那么自然而然就会想到useMemo,它使得数据项真正的改变时候才会使得useCallback重新执行。或者使用JSON.stringify转换params 即可。


params = useMemo(() => (params), []);

这里有个较为完整的例子,如何使用hooks分页请求表格数据:分页请求

作者:wuwei123
链接:https://juejin.im/post/5e1be062518825267f6996c0

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:react hook 初体验

链接:https://www.javascriptc.com/3835.html

« 理解promise、 generator 、async & await 之间的联系
团队在高速扩张中的能力构建与质量保证»
Flutter 中文教程资源

相关推荐

QR code