1.useMemo
具有缓存功能,可避免频繁的计算。(性能优化)
import React,{useState,useMemo,memo} from 'react';
const Demo = memo(function Child2(props){
const transferGender= (gender)=>{
return gender=='0' ?'男':'女';
}
const gender = useMemo(()=>
transferGender(props.gender)
,[props.gender])
return (
<p>{gender}:{props.count}</p>
)
})
export default Demo;
2.useCallBack
可以将父传子的函数保存起来,待下次组件渲染时不会重新渲染该函数(性能优化)
import React, {useState,useCallback} from "react";
import {View,Text,Button,StyleSheet} from 'react-native';
import Child1 from './Child1';
export default function CallBackHookDemo(){
const [count,setCount] = useState(0);
const [show,setShow] = useState(true);
const increment2 = useCallback(()=>{
console.log('执行increment2函数');
setCount(count+1);
},[count])
return(
<View style={styles.container}>
<Text>CallBackHookDemo:{count}</Text>
<Child1 increment={increment2}/>
<Button title={'show切换'} onPress={(e) =>setShow(!show)}/>
</View>
)
}
3.useCallBackReducer
可以在dispatch的第二个参数放入一个回调函数,当状态更新完毕后会执行这个回调函数,回调函数的第一个参数是新的状态值,在函数体中可以进行逻辑操作。
/*
* @Description:coderYYA
* @Date: 2022-03-17 18:03:05
* @LastEditTime: 2022-03-29 23:07:58
* @FilePath: \test3\src\hooks\useCallBackReducer.js
*/
import { useEffect, useRef, useReducer } from 'react'
const useCallBackReducer = (reducer, initialState, deps) => {
// 1、生成状态
const [state, dispatch] = useReducer(reducer, initialState)
// 2、使用一个持久化值记录回调函数
const isUpdate = useRef()
// 记录依赖,默认是监听全部状态值
let watchEffect = [state]
// 4、判断是否传入第三个参数,如果有且是数组,则进入分支
if (Array.isArray(deps)) {
if (deps.length) {
// 4.1、数组具有长度,则将数组设置为依赖
let newArr = []
deps.forEach((item) => {
newArr.push(state[item])
})
watchEffect = newArr
} else {
// 4.1、数组没有长度,则只在组件挂载时执行一次,意义不大
watchEffect = []
}
}
// 5、副作用函数,每次依赖数组中对应的状态更新后会执行回调函数
useEffect(() => {
//7、状态更新后会执行回调函数,在回调函数第一个参数可以获取到最新的状态
if (isUpdate.current) {
// 注:不设置回调函数的话,在第6步的时候,isUpdate.current 是undefined,不进入分支,所以不会执行回调函数
isUpdate.current(state)
}
}, watchEffect)
const setState = (action, cb) => {
//6、劫持dispatch,将回调函数赋予isUpdate.current,再执行dispatch进行状态加工
isUpdate.current = cb
dispatch(action)
}
return [state, setState]
}
export default useCallBackReducer
4.useCallBackState
可以在setState的第二个参数放入一个回调函数,当状态更新完毕后会执行这个回调函数,回调函数的第一个参数是新的状态值,在函数体中可以进行逻辑操作。
// useState的回调版,
// 可以在第二个参数=>回调函数的第一个参数nextValue中拿到更新的state值,并在函数体中执行某些逻辑操作
// setState(
// (preValue) => preValue + value,
// (newValue) => {
// 逻辑操作
// }
// )
import { useEffect, useRef, useState } from 'react'
const useCallBackState = (initState) => {
const [state, setState] = useState(initState)
const isUpdate = useRef()
const setCallBackState = (state, cb) => {
setState((preValue) => {
isUpdate.current = cb
return typeof state === 'function' ? state(preValue) : state
})
}
useEffect(() => {
if (isUpdate.current) {
// 不设置回调函数的话 isUpdate.current 是undefined,所以不会执行
isUpdate.current(state)
}
}, [state])
return [state, setCallBackState]
}
export default useCallBackState
5.useRef + forwardRef + useImperativeHandle
在父组件中 获取modal模态框的显示和隐藏事件
// 父组件
import React, { useRef } from 'react'
import YaForm from './Form'
import YaModal from '@/component/Modal'
import { Button } from 'antd'
const YaLogin = () => {
const modalRef = useRef()
const handleShowModal = () => {
modalRef.current.showModal()
}
const handleCloseModal = () => {
modalRef.current.closeModal()
}
return (
<div>
<Button type="primary" onClick={handleShowModal}>
点击登录弹窗
</Button>
<YaModal
ref={modalRef}
title="登录窗口"
children={<YaForm handleCloseModal={handleCloseModal} />}
/>
</div>
)
}
export default YaLogin
// 子组件(modal模态框)
import React, { useState, forwardRef, useImperativeHandle } from 'react'
import { Button, Modal } from 'antd'
const YaModal = (props, ref) => {
const [isModalVisible, setIsModalVisible] = useState(false)
useImperativeHandle(ref, () => {
return {
showModal,
closeModal,
}
})
const showModal = () => {
setIsModalVisible(true)
}
const closeModal = () => {
setIsModalVisible(false)
}
const handleOk = () => {
setIsModalVisible(false)
}
const handleCancel = () => {
setIsModalVisible(false)
}
return (
<div>
<Modal
title={props.title ? props.title : '弹出窗'}
visible={isModalVisible}
footer={props.footer ? true : false}
onOk={handleOk}
onCancel={handleCancel}
>
{props.children}
</Modal>
</div>
)
}
export default forwardRef(YaModal)
6.useTitile
在SPA页面切换时更换标签的标题
import { useEffect } from 'react'
const useTitle = (title) => {
useEffect(() => {
document.title = title
}, [])
return
}
export default useTitle
7.useContext
实现最高或上一级组件向后代传递数据的hook
// 父组件生成 context
export const UserContext = createContext()
// 用 UserContext 包裹需要接受数据的子组件
<UserContext.Provider value={name:"孙悟空"}>
<子组件/>
</UserContext.Provider>
// 子组件使用context
import React, { useState, useEffect, useContext } from 'react'
import { UserContext } from '../../APP.js'
export default function Recommend() {
const userContext = useContext(UserContext)
console.log(userContext) //取得父组件传递的数据
return (
<div>
<h2>{userContext.name}<h2>
</div>
)
}