• React-Hooks用法:useState()、useEffect()、useRef()


    在这里插入图片描述

    欢迎来到我的博客
    📔博主是一名大学在读本科生,主要学习方向是前端。
    🍭目前已经更新了【Vue】、【React–从基础到实战】、【TypeScript】等等系列专栏
    🛠目前正在学习的是🔥 R e a c t 框架 React框架 React框架🔥,中间穿插了一些基础知识的回顾
    🌈博客主页👉codeMak1r.小新的博客

    本文被专栏【React–从基础到实战】收录

    🕹坚持创作✏️,一起学习📖,码出未来👨🏻‍💻!
    在这里插入图片描述

    本节任务:能够理解hooks的概念以及解决的问题
    文章末尾有两个小案例,相信看完文章的你可以自己把小案例实现出来~

    React Hooks/Hooks是什么?

    Hooks的本质:一套能够使函数组件更加强大,更加灵活的“钩子”

    React体系里组件分为类组件 和 函数式组件。

    经过多年实战,函数组件是一个更加匹配React的设计理念UI = f(data),也更有利于逻辑拆分与重用的组件表达形式,而先前的函数组件是不可以有自己的状态的,为了能让函数组件可以拥有自己的状态,所以从react v16.8开始,Hooks应运而生。

    注意:

    1. 有了hooks之后,为了兼容老版本,class类式组件并没有被移除,两者都可以使用;
    2. 有了hooks之后,不能把函数当成无状态组件了,因为hooks为函数组件提供了状态;
    3. hooks只能在函数组件中使用

    Hooks解决了什么问题?

    Hooks的出现解决了两个问题:1. 组件的状态逻辑复用; 2. class组件自身的问题

    1. 组件的逻辑复用

    ​ 在hooks出现之前,react先后尝试了 mixin 混入,HOC高阶组件,render-props等模式…但是都有各自的问题,比如 mixin的数据来源不清晰,高阶组件HOC的嵌套问题等等…

    1. class组件自身的问题

    ​ class组件就像一个厚重的战舰一样,大而全,提供了很多东西,有不可忽视的学习成本,比如各种生命周期,this指向问题等等,而我们更多时候需要的是一个轻快灵活的快艇

    Hooks优势总结

    1. 告别难以理解的Class
    2. 解决业务逻辑难以拆分的问题
    3. 使状态逻辑复用变得简单可行
    4. 函数组件在设计思想上,更加契合React的理念

    三个常用的Hook

    (1) S t a t e H o o k : R e a c t . u s e S t a t e ( ) State Hook:React.useState() StateHookReact.useState()

    (2) E f f e c t H o o k : R e a c t . u s e E f f e c t ( ) Effect Hook:React.useEffect() EffectHookReact.useEffect()

    (3) R e f H o o k : R e a c t . u s e R e f ( ) Ref Hook:React.useRef() RefHookReact.useRef()

    1.State Hook

    1. State Hook让函数组件也可以有state状态,并进行状态数据的读写操作;

    2. 语法:

      const [xxx, setXxx] = React.useState(initValue)
      
      • 1
    3. useState()说明:

      参数:第一次初始化指定的值在内部作缓存;

      返回值:包含2个元素的数组,第1个为内部当前状态值,第2个为更新状态值的函数;

    4. setXxx()2种写法:

      setXxx(newValue):参数为非函数值,直接指定新的状态值,内部用其覆盖原来的状态值;

      setXxx(value => newValue):参数为函数,接收原本的状态值,返回新的状态值,内部用其覆盖原来的状态值

    示例

    import React, { useState } from 'react';
    
    function Example() {
      // 声明一个叫 "count" 的 state 变量
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>You clicked {count} times</p>
          <button onClick={() => setCount(count + 1)}>
            Click me
          </button>
        </div>
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    等价的 class 示例

    class Example extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          count: 0
        };
      }
    
      render() {
        return (
          <div>
            <p>You clicked {this.state.count} times</p>
            <button onClick={() => this.setState({ count: this.state.count + 1 })}>
              Click me
            </button>
          </div>
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    state 初始值为 { count: 0 } ,当用户点击按钮后,我们通过调用 this.setState() 来增加 state.count

    2.Effect Hook

    1. Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类式组件中的生命周期钩子)

    2. React中的副作用操作:

      (1)发送ajax请求获取数据

      (2)设置订阅/ 启动定时器

      (3)手动更改真实DOM

    3. 语法和说明:

      useEffect(() => {
      	// 在此可以执行任何带副作用操作
      	return () = > { //componentWillUnmount
      		// 做一些收尾的工作,比如清除定时器/取消订阅等等...
      	}
      },[stateValue])  
      //如果指定的是[],useEffect第一个参数的回调函数相当于componentDidMount()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    4. 可以把 useEffect Hook 看做如下三个函数的组合:

      componentDidMount()

      componentDidUpdate()

      componentWillUnmount()

    useEffect第二个参数传入不同的值:

    useEffect第二个参数useEffect第一个参数相当于理解

    不传第二个参数
    componentDidMount()
    +
    componentDidUpdate()
    组件挂载时会调用;
    并且所有的state都会监测
    传入空数组:[]componentDidMount组件挂载时会调用;
    并且所有的state都不监测
    传入数组:[stateValue]
    比如:[count]
    componentDidMount
    +
    count状态改变时的componentDidUpdate()
    组件挂载时会调用;
    并且监测count的改变

    useEffect第一个参数返回值:

    useEffect(() => {
        let timer = setInterval(() => {
          setCount(count => count + 1)
        }, 1000)
        return () => {
          console.log('componentWillUnmount')
          clearInterval(timer)
        }
      }, [])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    useEffect第一个参数的返回值是一个函数,就相当于生命周期函数:componentWillUnmount()

    示例

    import React, { useState, useEffect } from 'react';
    import root from '../../index'
    
    export default function Demo() {
    
      const [count, setCount] = useState(0)
    
      useEffect(() => {
        let timer = setInterval(() => {
          setCount(count => count + 1)
        }, 1000)
        return () => {
          console.log('componentWillUnmount')
          clearInterval(timer)
        }
      }, [])
    
      function increment() {
        // setCount(count + 1)
        setCount((count) => {
          return count + 1
        })
      }
      function unmount() {
        root.unmount();
      }
      return (
        <div>
          <h2>当前求和为:{count}</h2>
          <button onClick={increment}>点我+1</button>
          <button onClick={unmount}>卸载组件</button>
        </div>
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    3.Ref Hook

    1. Ref Hook 可以在函数组件中存储/查找组件内的标签或者任意其他数据;

    2. 语法:

      const refContainer = useRef()
      
      • 1
    3. 作用:保存标签对象,功能与React.createRef()一样

    示例

    // 创建容器
    const myRef = useRef()
    
    // 绑定容器
    <input type="text" ref={myRef} />
    <button onClick={show}>点我展示数据</button>
    
    function show() {
      // console.log(myRef)
      alert(myRef.current.value)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    阶段小练习 - 自定义hook

    1.需求描述:自定义一个hook函数,实现获取滚动距离Y

    const [ y ] = useWindowScroll() y就是滚动到顶部的距离

    在这里插入图片描述

    每次都有两次控制台输出是因为:React的StrictMode严格模式,忽略第二个输出即可。

    import { useState } from 'react';
    
    export default function useWindowScroll() {
      const [y, setY] = useState(0)
      // 在滚动行为发生的时候,不断获取滚动值,然后交给y
      window.addEventListener('scroll', () => {
        const h = document.documentElement.scrollTop
        setY(y => h)
      })
      return [y]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    import React from 'react'
    import useWindowScroll from './components/9_hooks_useWindowScroll'
    
    export default function App() {
      const [y] = useWindowScroll()
      console.log(y)
      return (
        <div style={{ height: '12000px' }}>
        </div>
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.需求描述:自定义hook函数,可以自动同步到本地LocalStorage

    1. message可以通过自定义传入默认初始值
    2. 每次修改message数据的时候,都会自动往本地同步一份到LoaclStorage中
    import { useState, useEffect } from 'react'
    
    export default function useLocalStorage(key, defaultValue) {
      const [message, setMessage] = useState(defaultValue)
      // 每次只要message变化,就会自动同步到本地LocalStorage
      useEffect(() => {
        window.localStorage.setItem(key, message)
      }, [message, key])
      return [message, setMessage]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    import React from 'react'
    import useLocalStorage from './components/10_hooks_useLocalStorage'
    
    export default function App() {
      const [message, setMessage] = useLocalStorage('hook-key', 'tom')
      setTimeout(() => {
        setMessage('abc-message')
      }, 5000)
      return (
        <div>
          <h4>{message}</h4>
        </div>
      )
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    做好文件外发管理,助力企业安全高效的进行文件共享
    精通 VS 调试技巧,学习与工作效率翻倍!
    云效流水线docker部署 :node.js镜像部署VUE项目
    Qt creator day3练习
    程序员写博客如何赚钱「5大盈利方向」
    多线程知识-13
    win11+vs2022配置ceres库
    pip出现的问题
    【最佳实践】瀚高数据库 Windows企业版v6.0.4 的安装
    .NET性能优化-快速遍历List集合
  • 原文地址:https://blog.csdn.net/Svik_zy/article/details/126079381