react的hook

为什么会有Hooks?

介绍Hooks之前,首先要给大家说一下React的组件创建方式,一种是类组件,一种是纯函数组件,并且React团队希望,组件不要变成复杂的容器,最好只是数据流的管道。开发者根据需要,组合管道即可。也就是说组件的最佳写法应该是函数,而不是类。。

但是我们知道,在以往开发中类组件和纯函数组件的区别是很大的,纯函数组件有着类组件不具备的多种特点,简单列举几条

纯函数组件没有状态
纯函数组件没有生命周期
纯函数组件没有this
只能是纯函数

这就注定,我们所推崇的函数组件,只能做UI展示的功能,涉及到状态的管理与切换,我们不得不用类组件或者redux,但我们知道类组件的也是有缺点的,比如,遇到简单的页面,你的代码会显得很重,并且每创建一个类组件,都要去继承一个React实例,至于Redux,更不用多说,很久之前Redux的作者就说过,“能用React解决的问题就不用Redux”,等等一系列的话。关于React类组件redux的作者又有话说

大型组件很难拆分和重构,也很难测试。
业务逻辑分散在组件的各个方法之中,导致重复逻辑或关联逻辑。
组件类引入了复杂的编程模式,比如 render props 和高阶组件。

什么是Hook:

Hook是react 16.7新增的一个特性,主要是用来让无状态组件(函数式组件)可以使用状态,以前为了进行状态管理,需要使用类组件或者redux等来管理,相当于类组件中的state,只不过用useState去代替了,useState() = this.state(),setVal() = this.setState()

Hooks’的单词意思为“钩子”。React Hooks 的意思是,组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码”钩”进来。而React Hooks 就是我们所说的“钩子”。那么Hooks要怎么用呢?“你需要写什么功能,就用什么钩子”。对于常见的功能,React为我们提供了一些常用的钩子,当然有特殊需要,我们也可以写自己的钩子。

下面是React为我们提供的默认的四种最常用钩子

useState()
useContext()
useReducer()
useEffect()

不同的钩子为函数引入不同的外部功能,我们发现上面四种钩子都带有use前缀
React约定,钩子一律使用 use前缀命名。所以,你自己定义的钩子都要命名为useXXX

React Hooks的用法:

深挖hook中常用的四个API

一、useState():

  1. useState 是用来定义一个状态的,相当于类组件中的state,只不过用useState去代替了,它与类组件的状态不同,函数组件的状态可以是对象也可以是基础类型数据,
  2. useState返回的是一个数组,第一个是当前的状态值,第二个是对象,表明用于更改状态的函数(类似于setState)
import React,{useState} from 'react';
import './App.css';

function App() {
  // useState创造1个状态,赋值一个初始值,当前赋值的初始值为0
  // 数组的第一个是一个变量,此变量指向当前状态的值,相当于this.state
  // 数组的第二个是一个函数,次函数可以修改状态的值,相当于this.setState
  const [count,setCount] = useState(0);
  const addCount = ()=>{
   
    setCount(count+10);
  }
  return (
    <div className="App">
      <div>{count}</div>
      <button onClick={addCount}>点击加1</button>
    </div>
  );
}

export default App;

注意: 设置值的时候必须返回一个新的值,可以使用…展开运算符辅助

import React, {useState} from 'react'
function App(){
let [obj,setObj] = useState({
         name:"Gseg",
         age:12
  })
return (
    <div>
	    <h2>{obj.name}</h2>    
   			//Object.assign(obj,{age:20}),这不算返回新值
		<button onClick={()=>{ setObj({...obj,name:"111111"}) }}>set</button>
	</div>
  )
}
export default App;

特别的: 设置的API可以传入一个函数,当传入是一个函数的时候,参数默认为count现在的值

import React, { useState } from 'react'
function App() {
  let [count, setCount] = useState(10)

  let handleClick = () => {
    //x默认为count现在的值
    setCount(x => {
      console.log(x)
      return x + 1   //返回的值即为修改的值
    })
  }

  return (
    <div>
      {count}
      <button onClick={handleClick}>+1</button>
    </div>
  )
}
export default App;

二、useEffect():

可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和componentWillUnmount 这三个函数的组合
useEffect的使用大致可以分为四种情况:

情况一: useEffect( ()=>{ } )
只有第一个参数的时候
此时相当于componentDidMount + componentDidUpdate钩子的组合,初次渲染并且状态改变时都会触发

情况二:useEffect(()=>{ },[loading])
当有第二个参数(是一个非空数组)时,那么回调函数会依据数组的变化而调用
可以监听一些状态的改变

情况三:useEffect(()=>{ },[])
第二个参数写一个空数组
只在初次componentDidMount时执行一次

情况四:useEffect(()=>{ return ()=>{ console.log(“组件将要被卸载了”) } })
useEffect中返回一个函数
此时相当于componentWillUnmount 钩子, 卸载组件的时候触发

import React,{ useEffect,useState } from 'react';
import './App.css';

function App() {
  const [loading,setLoading] = useState(true)
 
  //情况一:
  //只有第一个参数
  // 相当于componentDidMount + componentDidUpdate 
  useEffect(()=>{
    console.log("11")
    setTimeout(() => {
      setLoading(false)
    }, 3000);
  })

  //情况二:
  //当有第二个参数(是一个数组)时,那么回调函数会依据数组的变化而调用
  //可以监听一些状态的改变
  useEffect(()=>{
    console.log("loading的值发生了改变")
  },[loading])

  //情况三:
  //写一个空数组,只在初次componentDidMount时执行一次
  useEffect(()=>{
    console.log("初次渲染")
  },[])

  //情况四
  //useEffect中返回一个函数
  //卸载组件的时候触发
  useEffect(()=>{
    return ()=>{ console.log("组件将要被卸载了")  }
  })


 
  let handleChange = ()=>{
    setLoading(!loading)
  }

  return (
  <div>
    {loading?<div>Loading...</div>:<div>内容加载完毕</div>}
    <button onClick={handleChange}>取反</button>
  </div>
  )
  
}

export default App;

三、useContext():

如果想要组件之间共享状态,可以使用useContext。
需要与createContext()配合使用
React 的 Context API 是一种在应用程序中深入传递数据的方法,而无需手动一个一个在多个父子孙之间传递prop。当咱们需要的只是传递数据时,它可以作为像Redux这样的工具的一个很好的替代。

import React,{ useContext} from 'react';
import './App.css';

function App() {
  // useContext共享状态钩子
  const AppContext = React.createContext()

  const Achild = ()=>{
    const {name} = useContext(AppContext)
    return (
      <div>这是组件a,使用的name值是:{name}</div>
    )
  }

  const Bchild = ()=>{
    const {name,age} = useContext(AppContext)
    return (
      <div>
         <div>这是组件B,使用的name值是:{name}</div>
         <div>这是组件B,使用的age值是:{age}</div>
      </div>
    )
  }

  return (
    //共享{name:"zhangsan",age:21} 数据
    <AppContext.Provider value={{name:"zhangsan",age:21}} >
      <Achild></Achild>
      <Bchild></Bchild>
    </AppContext.Provider>
  );
}

export default App;

四、useReducer():

import React, { useReducer } from 'react';
import './App.css';

function App() {
  // useReducer 
  const reducer = (state, action) => {
    switch (action.type) {
      case "add":
        return {
          ...state, count: state.count + 10
        }
      case "sub":
        return {
          ...state, count: state.count - 10
        }
      case "addCustom":    //自定义加值
        return {
          ...state, count: state.count + action.value
        }
      default:
        return state
    }
  }
  const [state, dispatch] = useReducer(reducer, { count: 10 })

  const addCount = () => {
    dispatch({
      type: 'add'
    })
  }
  const subCount = () => {
    dispatch({
      type: 'sub'
    })
  }

  const addCountCustom = () => {
    dispatch({
      type: 'addCustom',
      value:100
    })
  }

  return (
    <div>
      <div>{state.count}</div>
      <button onClick={addCount}>点击+10</button>
      <button onClick={subCount}>点击-10</button>
      <button onClick={addCountCustom}>自定义加值</button>
    </div>
  );
}

export default App;

自定义hook:

自定义钩子函数,因为react-hook的API都是以use开头的,所以按照规范,自定义的hook都以use开头去封装,便于阅读和区分,自定义hook,和普通的函数本质上没有区别,都是一些函数的封装,方便使用

 注意:
    1.自定义hook,必须以use开头
    2.自定义hook,可以使用我们这些hook,(useState,useEffect...)来封装

import React, {useState} from 'react'

const useCus = (val, num) => {
  let [count, setCount] = useState(val)

  const add = () => {
	setCount(count + num)
  }

  return { count, add }
}


function App() {
  let { count, add } = useCus(10, 6)
  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => { add() }}>+</button>
    </div>
  )
}

export default App;

除此之外,HOOK还有useCallback, useMemo, useRef等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明 YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明YOLO高分设计资源源码,详情请查看资源内容使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值