最近在学习react相关的东西,记录一下react函数式编程中的Hooks相关内容;
Hooks要解决的问题:
在函数式组件中,不能使用类组件中的state和生命周期写法,Hooks让函数式组件,能够更简洁的实现react的一系列特性。
Hooks主要包含的内容有:
一、组件状态管理钩子
useState:组件状态管理的钩子,相当于类组件中定义state和setState
import { useState } from 'react';
//state 状态值
//setState 更新状态值的方法
//initState 初始值
const [state, setState] = useState(initState)
注:setState方法可以接受一个带返回值的函数,函数参数为上一个状态值。
useReducer:复杂组件状态管理的钩子,useState 加强体,简单状态管理使用useState比较方便
import { useReducer} from 'react';
//state 状态值
//dispatch 设置状态的方法,方法接收一个对象action为参数,对象内主要描述如何操作等内容(删除、新增等)
//reducer 调用dispatch 时,更新状态的方法,方法接收当前状态值、调用dispatch传入的对象两个参数
//initState 初始值
//initAction 初始化时使用的action
const [state, dispatch] = useReducer(reducer, initState, initAction)
useContext:父子组件的数据共享,可嵌套,就近原则
import React from 'react';
// 创建一个 Context 对象,在组件渲染中订阅这个对象
const MyContext = React.createContext({title:'123'});
export default MyContext;
import {useContext}from 'react';
import MyContext from './MyContext';
// 创建父组件,通过Context.Provider返回的组件给context赋值
const Person = () => {
return(
<MyContext.Provider value={{ content: '9999' }}>
<Content></Content>
</MyContext.Provider>
)
}
export default Person
import {useContext}from 'react';
import MyContext from './MyContext';
// 创建子组件,通过Context.Consumer返回的组件进行渲染,或者订阅刚才创建的Context对象,进行取值
const Content = () => {
//取得最近的Context.Provider 的值
const {content} = useContext(MyContext);
return(
<MyContext.Consumer>
{value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>
)
}
export default Content
二、副作用处理钩子
useEffect:副作用处理的钩子;react生命周期componentDidMount、componentDidUpdate、componentWillUnmount的统一
import { useEffect } from 'react'
useEffect(() => {
//副作用处理
return () => {
//componentWillUnmount时执行,或者重复渲染时,执行副作用钩子前执行
}
}, array)
array:可选数组。省略,每次渲染都会执行;空数组,只会在组件挂载/卸载时执行一次;非空数组,会在数组元素发生改变后执行,且这个变化的比较是浅比较
useLayoutEffect:副作用处理的钩子;用法与useEffect一致;
区别:
useEffect是异步的,不会阻碍浏览器更新;
useLayoutEffect是同步的,在浏览器二次渲染时,在渲染前发生,一般用于要测量某个DOM的尺寸,进行重新渲染
三、DOM操作钩子
useRef:创建ref,操作DOM
import { useRef} from 'react';
const Test = () => {
//创建ref
const inputRef = useRef();
const getValue = () => {
//访问ref
const inpt = inputRef.current; // input的DOM对象
inpt.focus(); // 让 input 框获取焦点
console.log(inpt.value); // input输入框的值
};
return (
<div>
<input ref={ inputRef } type="text" />
<button onClick={ getValue }>Click me</button>
</div>
);
}
四、性能优化钩子,建立缓存,根据依赖项来决定是否在重新渲染时进行新的值计算、函数创建
useMemo:缓存的是一个值,避免每次重新渲染都去进行大量的计算该值,主要用于复杂列表、对象深拷贝等复杂计算中;
import { useMemo} from 'react';
//不使用缓存
//每次重新渲染,都会执行函数去重新计算(不论函数中是否使用到变化的状态值)
const Demo = () => {
//逻辑处理
return 666;
}
//使用缓存
//只有array中的值发生变化,才会重新计算
const MemoDemo = useMemo(() => {
//逻辑处理
reunt 666;
}, array);
return <div>{MemoDemo}</div>;
注:不能把副作用处理逻辑放到useMemo中,应该使用useEffect
useCallback:缓存的是一个函数,避免父组件更新时,通过props传递给子组件的函数非必要重新创建,而使用缓存的函数;
import { useCallback} from 'react';
//不使用缓存
//父组件每次重新渲染,都会重新通过props传递给子组件一个新的函数(不论该函数是否需要更新)
const Demo = () => {
return <div>{username}</div>;
}
//使用计算缓存
//只有array中的值发生变化,才会重新传递给子组件一个新的函数
const callbackDemo = useCallback(() => {
return <div>{username}</div>;
}, array);
return (
<div>
<MySon renderForm={callbackDemo}></MySon>
<div>
)