ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于hooks,你该知道的

2022-01-08 09:05:57  阅读:175  来源: 互联网

标签:count function getFetchUrl 渲染 hooks effect 关于 useEffect 知道


图片

 关于hooks使用,你该知道的,可以看看

首先,还是拿第一个hook例子来说。


const count=useCounter()
//别的地方调用了这个hook
function useCounter(){
console.log('调用了count')
// 这里是每次都打印出来的
const [count,setCount]=useState(0)
// useEffect(()=>{
//     setInterval(() => {
//         console.log('useCounter',count)
//         setCount(count + 1);
//     }, 1000);      
// },[])
// 这里的count取的是初始执行这个useEffect时候的值,
// 也就是0,所以每次加计算的都是从0开始,
// 所以这里的值应该会一直是0
// useEffect(()=>{
//     let id=setInterval(() => {
//         console.log('useCounter',count)
//         setCount(count + 1);
//     }, 1000);
// },[count])
// 每次重新执行,setInterval都是会重新定义,
// 所以需要一个全局变量来保存这个东西,比如用一个ref来保存,
// 或者使用函数模式设置count
    useEffect(()=>{
let id=setInterval(() => {
console.log('useCounter',count)
            setCount(c=>c+1);
        }, 1000);
// 不需要传入依赖,只执行一次,setInterval不会重置,
// setCount的函数设置方式,可以实现我们的效果
    },[])
// 或者全局挂在一个ref上面
return [count]
}

可以看出,hook的每一次渲染都会走到hook里面。

  • 这个里面好像是因为count值会变化,外面引用到了,所以每次都会重新渲染useCounter这个函数。

  • 但是这个里面的useEffect其实只会调用一次。

每一次渲染都有自己的事件处理函数,包括传入的参数

  • 我们的组件函数每次渲染都会被调用,每次调用的count都是常量,并且他被赋予了当前渲染中的状态值,所以才会有如果函数依赖外面的参数,就要把参数传入到第二个参数里面,当参数发生变化就让这个函数重新创建一遍。

  • 每一次渲染都有一个“新版本”的handleClick,每一个版本的handleClick都记住了自己的event。

  • vue更像是把所有数据都存在一个地方,每次用到参数的时候都去那里找当前最新的,这个函数一旦定义好就不变了。

  • 在任意一次的渲染中,props和state始终是不变的,props和state在不同的渲染中是相互独立的,所以使用到他们的任意值也都是相互独立的,他们都属于一次特定的渲染。即使事件处理中的异步函数调用“看到”的也是这次渲染中的值。也有可能不是最新的值。

effect:每次渲染都有他自己的effects

  • 并不是count值在“不变”的effect中发生了改变,而是effect函数本身在每一次渲染中都不同,如果effect依赖于外部的count值,那么每一个版本的effect应该都是根据最新的count来创建的。

  • 虽然effect是一个,但是每次渲染都是一个不同的函数,并且每个effect函数得到的props,或者state都来自属于他的那次特定渲染。

  • effect渲染的时间。

function Counter() {
  // ...
  useEffect(
    // Effect function from first render
    () => {
      document.title = `You clicked ${0} times`;
    }
  );
  // ...
}

// 渲染状态为 0时候的UI。

// 需要渲染的内容: <p>You clicked 0 times</p>。
// 渲染完了之后调用这个
// () => { document.title = 'You clicked 0 times' }。
// 开始更新UI,给DOM添加一些东西。
// 绘制到屏幕上。
// 运行给我的effect

// 运行 () => { document.title = 'You clicked 0 times' }。

// 初次渲染
function Counter() {
  // ...
  useEffect(
    // Effect function from second render
    () => {
      document.title = `You clicked ${1} times`;
    }
  );
  // ...
}

// React: 渲染状态为 1时候的UI。

// 需要渲染的内容: <p>You clicked 1 times</p>。
// 渲染完了之后调用
// effect:() => { document.title = 'You clicked 1 times' }。
// 开始更新UI,修改了DOM。
// 更改绘制到屏幕上了。
// 运行渲染effect

// 运行 () => { document.title = 'You clicked 1 times' }。
function Counter() {
  // ...
  useEffect(
    // Effect function from third render
    () => {
      document.title = `You clicked ${2} times`;
    }
  );
  // ..
}

1 .所有effects都会在渲染之后依次执行,概念上他只是组件输出的一部分,并且可以看到某次特定渲染的props和state。
2 .和这个不同的是之前的this.state.count,这种模式,只是会获取到最新的数据。

effect清理上次的函数

// 错误的认识:
// 假设第一次渲染的时候props是{id: 10},
// 第二次渲染的时候是{id: 20}

// 清除了 {id: 10}的effect。
// 渲染{id: 20}的UI。
// 运行{id: 20}的effect

// 正确的
// 渲染{id: 20}的UI。
// 屏幕上可以看到{id: 20}的UI。
// 清除{id: 10}的effect。
// 运行{id: 20}的effect。
// effect的清除并不会读取最新的props,
// 他只能读取到定义他的那次渲染的props值
  • react会根据我们当前的props,state同步到DOM。

  • useEffect使你能够根据props和state同步react tree之外的东西。

  • react并不能区分effects的不同,所以为了避免不重复的调用,可以给useEffect一个依赖数组参数。


useEffect(() => {
    document.title = 'Hello, ' + name;
  }, [name]); // Our deps
// 保证只使用了渲染中的name

// 如果当前渲染中的这些依赖项和上一次运行这个effect的时候值一样,
// 因为没有什么需要同步React会自动跳过这次effect:
  • 即使依赖数组中只有一个值在两次渲染中不同,也不会跳过effect的运行,会同步所有

移除依赖的常见方式

1. 让Effect自给自足,但是这种使用场景及其优先。放弃了外面修改state的权力。

useEffect(() => {
    const id = setInterval(() => {
      setCount(count + 1);
    }, 1000);
    return () => clearInterval(id);
}, [count]);

useEffect(() => {
    const id = setInterval(() => {
      setCount(c => c + 1);
    }, 1000);
    return () => clearInterval(id);
}, []);

2. 使用reducer,解耦行为和操作数据的两个过程。是当你dispatch的时候,React只是记住了action - 它会在下一次渲染中再次调用reducer。在那个时候,新的props就可以被访问到,而且reducer调用也不是在effect里。

这就是为什么我倾向认为useReducer是Hooks的“作弊模式”。它可以把更新逻辑和描述发生了什么分开。结果是,这可以帮助我移除不必需的依赖,避免不必要的effect调用。

3. 把函数移到effects里面

function SearchResults() {
  const [query, setQuery] = useState('react');
  useEffect(() => {
    function getFetchUrl() {
      return 'https://hn.algolia.com/api/v1/search?query=' + query;
    }
    // 这个effect依赖的函数1
    async function fetchData() {
      const result = await axios(getFetchUrl());
        setData(result.data);
    }
    // 这个effect以来的函数2
    fetchData();
  }, [query]); // OK
  // ...
}

4 .实在不能放到effects里面的情况


// 只执行一次的useEffect
function SearchResults() {
  function getFetchUrl(query) {
    return 'https://hn.algolia.com/api/v1/search?query=' + query;
  }

  useEffect(() => {
    const url = getFetchUrl('react');
    ...
  }, []);

// 没使用依赖,只会在初始化的时候执行一次,
  useEffect(() => {
    const url = getFetchUrl('redux');
    ...
  }, []);
  ...
}

// 函数作为依赖,会怎样呢?
function SearchResults() {
  function getFetchUrl(query) {
    return 'https://hn.algolia.com/api/v1/search?query=' + query;
  }

  useEffect(() => {
    const url = getFetchUrl('react');
  }, [getFetchUrl]);

  useEffect(() => {
    const url = getFetchUrl('redux');
  }, [getFetchUrl]);
}
//每次渲染其实函数都是新的,所以这个依赖完全是废的,
// 其实还是每次刷新都触发effect执行,也就是请求数据
// 解决方法1 :如果一个函数没有使用组件内的任何值,
// 就把他提到组件外面定义,然后就可以自由的在effect里面使用
function getFetchUrl(query) {
  return 'https://hn.algolia.com/api/v1/search?query=' + query;
}

function SearchResults() {
  useEffect(() => {
    const url = getFetchUrl('react');
  }, []);

  useEffect(() => {
    const url = getFetchUrl('redux');
  }, []);
  // 此时不需要再设为依赖,因为他不在渲染范围内,
  // 不会被数据流影响,不会因为props,state而改变
}

//解决方法2:包装为useCallck hook
function SearchResults() {
  const getFetchUrl = useCallback((query) => {
    return 'https://hn.algolia.com/api/v1/search?query=' + query;
  }, []);

  useEffect(() => {
    const url = getFetchUrl('react');
  }, [getFetchUrl]);

  useEffect(() => {
    const url = getFetchUrl('redux');
  }, [getFetchUrl]);
  // 本质上是给函数添加了一层依赖检查,只有函数依赖的参数发生变化,
  // 函数才会变化,而不是仅仅简单的去掉函数的依赖,
  // 那么effect依赖数组的检查是不是也可以这么来??
}

往期阅读

1、React Hooks介绍

2、React Hooks概览

3、使用 State Hook

4、使用 Effect Hook

5、Hooks使用规则

6、自定义 Hook

标签:count,function,getFetchUrl,渲染,hooks,effect,关于,useEffect,知道
来源: https://blog.csdn.net/qq_39606853/article/details/122375298

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有