React之5 编程式函数Hook

https://blog.csdn.net/uncle_huang/article/details/104621518?share_token=E6D169E9-617C-459E-927A-AC6A4EBABCD9&tt_from=mobile_qq&utm_source=mobile_qq&utm_medium=toutiao_ios&utm_campaign=client_share

Hook解决函数组件不能使用state的问题。函数式组件比class组件好用,这时候hook它来了,这样函数式组件也能使用state,岂不是爽歪歪。

5.1 新特性useState(组件状态管理钩⼦)
用法:

const [state,setState]=useState(initState)

state是要设置的状态
setState是更新state的⽅法,只是⼀个⽅法名,可以随意更改
initState是初始的state,可以是随意的数据类型,也可以是回调函数,但是函数必须是有返回值
App.js
使用Hook前

import React, { Component } from 'react'

export default class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
     count:0
    }
  Add(){
    this.setState(
      {
        count:this.state.count+1
      }
    )
  }
  render() {
    return (
      <div>
        <div>你点击了{this.state.count}</div>
        <button onClick={()=>this.Add()}>点击</button>
      </div>
    )
  }
}

使用Hook后(是不是感觉简洁了很多^^)

import React, { useState } from 'react'

const App = () => {
  const [count, setCount] = useState(0)
  return (
    <div>
      <div>你点击了{count}</div>
      <button onClick={() => setCount(count + 1)}>点击</button>
    </div>
  )
}
export default App

5.2 新特性useEffect(副作⽤处理钩⼦)
⼀般称数据获取、订阅、定时执⾏任务、⼿动修改ReactDOM这些⾏为都可以称为副作⽤
useEffect也是componentDidMount、componentDidUpdate和componentWillUnmount这⼏个⽣命周期⽅法的统⼀

用法

useEffect(callback,array)

callback: 回调函数,作⽤是处理副作⽤逻辑
callback可以返回⼀个函数,⽤作清理
useEffect(() =>{
 //副作⽤逻辑 xxxxxx
 return ()=>{
 //清理副作⽤需要清理的内容
 //类似于componentWillUnmount,组件渲染和组件卸载前执⾏的代码
 }
 },[])

array(可选参数):数组,⽤于控制useEffect的执⾏
数组分三种情况:
空数组,则只会执⾏⼀次(即初次渲染render),相当于componentDidMount
⾮空数组,useEffect会在数组发⽣改变后执⾏
不填array这个数组,useEffect每次渲染都会执⾏

import React, { useState, useEffect } from 'react'

const App = () => {
  const [count, setCount] = useState(0)
  useEffect(() => {
    document.title = `点击次数${count}`
    return () => {
      console.log('组件更新或卸载')
    }
  },[count])
  return (
    <div>
      <div>你点击了{count}</div>
      <button onClick={() => setCount(count + 1)}>点击</button>
    </div>
  )
}
export default App

5.3 新特性useContext

⼀般会使⽤第三⽅状态管理器来实现全局数据共享
redux
dva
mobx

useContext(context)是针对context上下⽂提出的⼀个Hooks提出的⼀个API,它接受React.createContext()的返回值作为参数,即context对象,并返回最近的context

使⽤useContext是不需要再使⽤Provider和Consumer的

当最近的context更新时,那么使⽤该context的hook将会重新渲染

使用context:

import React, { Component } from ‘react’

//创建上下文

const HahaContext=React.createContext()
const {Provider,Consumer}=HahaContext
let store={
  name:'uncleHuang',
  sex:'女'
}

class Info extends Component{
  render(){
    return(
      <Consumer>
        {
          store=>{
            return(
              <div>
          <p>姓名:{store.name}</p>
            <p>性别:{store.sex}</p>
              </div>
            )
          }
        }
      </Consumer>
    )
  }
}

function ToolBar(props){
  return(
    <div>
      <Info></Info>
    </div>
  )
}

class App extends Component {
  render() {
    return (
      <div>
        <h1>高阶组件上下文通信</h1>
        <Provider value={store}>
          <ToolBar></ToolBar>
        </Provider>
      </div>
    )
  }
}

export default App

使用useContext:

import React, { useContext } from 'react'

const Context=React.createContext({name:'uncleHuang',sex:'female'})
const App = () => {
  const value = useContext(Context)
  return (
    <div>
      <div>姓名:{value.name}</div>
    </div>
  )
}
export default App

5.4 新特性useReducer

useReducer是useState的⼀个增强体,可以⽤于处理复杂的状态管理
useReducer可以完全替代useState,只是我们简单的状态管理⽤ useState⽐较易⽤,useReducer的设计灵感源⾃于redux的reducer
对⽐⼀下useState和useReducer的使⽤:

//useState的使⽤⽅法
const [state,setState]=useState(initState)
//useReducer的使⽤⽅法
const [state,dispatch]=useReducer(reducer,initState,initAction)

reducer是⼀个函数,根据action状态处理并更新state
initState是初始化的state
initAction是useReducer初次执⾏时被处理的action
state状态值
dispatch是更新state的⽅法,他接受action作为参数
useReducer只需要调⽤dispatch(action)⽅法传⼊action即可更新state,使⽤如下

//dispatch是⽤来更新state的,当dispatch被调⽤的时候,reducer⽅法也会被调⽤,同时根据action的传⼊内容去更新state
action是传⼊的⼀个描述操作的对象

dispatch({type:'add'})

reducer是redux的产物,他是⼀个函数,主要⽤于处理action,然后返回最新的state,可以把reducer理解成是action和state的转换器,他会根据action的描述去更新state,使⽤例⼦:

(state,action) => Newstate

import React, { useReducer } from 'react'

const initState={count:0}
const reducer=(state,action)=>{
  switch(action.type){
    case 'reset':
      return initState;
    case 'add':
      return {count:state.count+1};
    case 'reduce':
      return {count:state.count-1};
    default:
      return state
  }
}
const App = () => {
  const [state, dispatch] = useReducer(reducer, initState)
  return (
    <div>
      <p>当前数量是:{state.count}</p>
      <div><button onClick={()=>dispatch({type:'reset'})}>重置</button></div>
      <div><button onClick={()=>dispatch({type:'add'})}>加一</button></div>
      <div><button onClick={()=>dispatch({type:'reduce'})}>减一</button></div>
    </div>
  )
}
export default App

useContext可以解决组件间的数据共享问题,⽽useReducer可以解决复杂状态管理的问题,如果把他们结合起来使⽤,就可以实现redux的功能了,意味着未来我们可以不再依赖第三⽅状态管理器了

5.5 官⽹介绍额外的Hooks
1、useMemo ⽤于性能优化,通过记忆值来避免在每个渲染上执⾏⾼开销的计算
适⽤于复杂的计算场景,例如复杂的列表渲染,对象深拷⻉等场景
使⽤⽅法如下

const memoValue =useMemo(callback,array)

callback是⼀个函数⽤于处理逻辑
array 控制useMemo重新执⾏的数组,array改变时才会 重新执⾏useMemo
useMemo的返回值是⼀个记忆值,是callback的返回值
不能在useMemo⾥⾯写副作⽤逻辑处理,副作⽤的逻辑处理放在useEffect内进⾏处理

import React, { useMemo } from 'react'

const obj1={name:'小驴',sex:'男',age:'12'}
const obj2={name:'小马',sex:'女',age:'13',like:'和小驴同学一起玩'}

const App = () => {
  const memoValue=useMemo(() => Object.assign(obj1,obj2), [obj1,obj2])
  return (
    <div>  
  <div>姓名:{memoValue.name}----年龄:{memoValue.age}</div>
    </div>
  )
}
export default App

2、UseCallback和useMemo⼀样,也是⽤于性能优化的
基本使⽤⽅法


const memoCallback= useCallback(callback,array)

callback是⼀个函数⽤于处理逻辑
array 控制useCallback重新执⾏的数组,array改变时才 会重新执⾏useCallback
跟useMemo不⼀样的是返回值是callback本身,⽽useMemo返回的是callback函数的返回值

const obj1 = { name: '小驴', sex: '男', age: '12' }
const obj2 = { name: '小马', sex: '女', age: '13', like: '和小驴同学一起玩' }

const App = () => {
  const memoCallBackValue = useCallback(() => Object.assign(obj1, obj2), [
    obj1,
    obj2
  ])
  return (
    <div>
      <div>
        姓名:{memoCallBackValue().name}----年龄:{memoCallBackValue().age}
      </div>
    </div>
  )
}
export default App

3、useRef ⽅便我们访问操作dom

import React, { useRef } from 'react'

const App = () => {
  //创建ref
 const ref = useRef()
 const getValue=()=>{
  //  访问ref
   console.log(ref.current.value)
 }
  return (
    <div>
      <input ref={ref} type="text"></input>
      <button onClick={getValue}>获取input值</button>
    </div>
  )
}
export default App

5.6 封装自定义Hooks

import React, { useEffect } from 'react'
//封装的Hooks⽤use开头
const useChangeTitle = title => {
  useEffect(() => {
    document.title = title
  }, [title])
}
export default props => {
  useChangeTitle('自定义修改标题Hooks')
  return <div>测试自定义Hooks</div>
}

5.7 React Hooks的使⽤规则

只在顶层调⽤Hooks
Hooks的调⽤尽量只在顶层作⽤域进⾏调⽤不要在循环,条件或者是嵌套函数中调⽤Hook,否则可能会⽆法确保每次组件渲染时都以相同的顺序调⽤Hook

只在函数组件调⽤Hooks
React Hooks⽬前只⽀持函数组件,所以别在class组件或者普通的函数⾥⾯调⽤Hook钩⼦函数

React Hooks的应⽤场景如下
函数组件
⾃定义hooks

文档更新时间: 2021-12-04 07:23   作者:admin