react Hooks是官方提供的新特性
文章先讲useState, useEffect , useRef , useContext ,useReducer 的基本用法
后面会将useCallback,useMemo配合Memo对项目进行优化,以及使用自定义hooks来复用逻辑
当然还有一些不常用的hooks(useLayoutEffect,)
useState (解决函数组件无状态的问题)
const [ data , setData ] = useState([])
[]为初始值,data为声明的变量,setData修改值的函数
假设这里是值一个数组
setData((old)=>{
const newVal = [...old]
return newval
})
注意点:1.class组件的this.setState更新是state是合并, useState中setData是替换。
2.setData()替换的对象不能是同一个,替换的意思是不同的对象(注意会有小坑)
3.setData((oldData)=>[...oldData,obj]) 参数是函数时,函数的参数是旧值,返回的是新值
useEffect (官方介绍是用来进行各种副作用的函数,相当于类组件的三个生命周期函数)
useEffect(() => {
return ()=> {}
},[data])
第一个函数是用来执行各种副作用的,函数的返回值
第二参数:
1.不传,组件每次 render 之后 useEffect 都会调用,相当与DidMount 和 DidUpdate
2.[],代表DidMount 和 WillUnmount 两个周期函数
3.传入一个数组,其中包括变量,只有这些变量变动时,useEffect 才会执行
注意点:1.data可以是任意值,包括传值过来的数据,声明的变量,页面跳转传参
2.useEffect 是在render之后生效执行的。(组件完成渲染之后在执行的)
useRef (获取dom,保存某些状态,父触发子方法/拿子的数据)(修改useRef的值是不会触发组件更新)
const dataRef = useRef()
<button ref={dataRef} />
dataRef.current
dataRef.current 是可以直接修改的
父触发子方法/拿子的数据(useRef,useImperativeHandle)
子组件中:
import {useImperativeHandle} from 'react'
const Children = ({parentRef})=> {
useImperativeHandle(parentRef,()=> ({
changeVal:(参数)=>{
},
childrenData:'123'
}))
}
父组件中
import {useRef} from 'react'
const Parent = () => {
const parentRef = useRef()
const updata = () => {
parent.current.changeVal(参数)
parnet.current.childrenData
}
return (
<div>
<Children parentRef={parentRef} /> //这里不要用ref绑定
</div>
)
useContext(实现组件的跨级传值但不能修改传入的值) useReducer(生成数据以及修改数据的函数)
这两个配合使用可以达到react-redux的效果
useContext用法
import { createContext } from 'react'
export const ParentState = createContext()
<ParentState.Provide value={ state } >
<组件>
</ParentState.Provide >
import {useContext} from 'react'
import {parentState} from '父组件'
const state = useContext(parentState)
useReducer 用法
import {useReducer} from 'react'
const [state,dispatch] = useReducer((oldState,action)=>{
switch (action.type) {
case 'add':
return oldState + action.num
default:
throw new error('Unexpected action')
}
},data)
<button onClick={dispatch({type:'add',num:3})}>
项目中两者结合可以达到全局状态管理的效果 利用useReducer生成数据以及修改数据的函数.
useContext将数据和函数全局共享 从而达到全局都可以修改这些数据
用法和redux很相似(用过的应该都知道)
以下是项目中对全局状态管理封装的store.js 向外暴露函数 调用即可拿到共享的数据以及函数
import React, { useReducer, useContext } from "react";
const stateStorage = sessionStorage.getItem("state");
export const initialState = stateStorage
? JSON.parse(stateStorage)
: {
panes: [{ title: "首页", path: "/Index", key: "1" }],
activeKey: "1",
position: [],
userInfo: {
audit_acc: [],
resp_acc: [],
user_id: '',
zzjg: {
layer: null,
prctr: null,
prctr_name: null,
},
},
};
const reducer = (state, action) => {
switch (action.type) {
case "PANES_":
return Object.assign({}, state, { panes: action.panes });
case "ACTIVEKEY_":
return Object.assign({}, state, { activeKey: action.activeKey });
case "POSITION_":
return Object.assign({}, state, { position: action.position });
default:
throw new Error("Unexpected action");
}
};
const SupportContext = React.createContext();
export const SupportProvider = ({ children }) => {
const contextValue = useReducer(
reducer,
JSON.parse(JSON.stringify(initialState))
);
return (
<SupportContext.Provider value={contextValue}>
{children}
</SupportContext.Provider>
);
};
const useSupportReducer = () => {
const contextValue = useContext(SupportContext);
return contextValue;
};
export default useSupportReducer;
其他组件中使用
import useSupportReducer from '@/store.js'
const [store, dispatch] = useSupportReducer()
dispatch({
type: 'PANES_',
panes:panes,
})