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

在这里插入图片描述

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

本文目录

  • React Hooks/Hooks是什么?
  • Hooks解决了什么问题?
  • Hooks优势总结
  • 三个常用的Hook
  • 1.State Hook
    • 示例
    • 等价的 class 示例
  • 2.Effect Hook
    • 示例
  • 3.Ref Hook
    • 示例
  • 阶段小练习 - 自定义hook

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

坚持创作✏️,一起学习,码出未来‍!
React-Hooks用法:useState()、useEffect()、useRef()_第1张图片

本节任务:能够理解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)
    
  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>
  );
}

等价的 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>
    );
  }
}

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()
    
  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)
    }
  }, [])

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>
  )
}

3.Ref Hook

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

  2. 语法:

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

示例

// 创建容器
const myRef = useRef()

// 绑定容器
<input type="text" ref={myRef} />
<button onClick={show}>点我展示数据</button>

function show() {
  // console.log(myRef)
  alert(myRef.current.value)
}

阶段小练习 - 自定义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]
}
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>
  )
}

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]
}
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>
  )
}

你可能感兴趣的:(React--从基础到实战,react.js,javascript,前端,react,hooks)