React Hook
React Hook
Hook 是 React 16.8 的新增一系列封装函数,它可以让函数组件中可以使用state,跨组件通信,生命周期等React的特性
Hook的意义在于:将函数组件中的业务逻辑抽离出来,保证组件UI的纯净化
内置Hook (10个)
1.useState
定义和修改state [修改state的方法得到的一定是新值]
基本语法:
//定义state和修改state的方法
const [name,setName]=useState<数据类型>(数据默认值)
//定义事件处理程序来修改state
const change=()=>{// setName()// setName((旧值)=>{return 修改后的值})
}
案例一:定义修改字符串
import Reac, { FC,useState} from "react";
interface IAppProps{}
const App:FC>=()=>{// todo 定义state和义修改state的方法const [name,setName]=useState('篮网')// todo 定义事件处理程序const set=()=>{setName('掘金')}return {name}
}
export default App;
案例二:定义修改数值(计数案例)
import Reac, { FC,useState} from "react";
interface IAppProps{}
const App:FC>=()=>{// todo 定义state和义修改state的方法const [count,addCount]=useState(1);// todo 定义事件处理程序const add=()=>{addCount((n)=>n+1)}return
}
export default App;
案例三:定义修改数值(计数案例)
import Reac, { FC,useState} from "react";
interface IAppProps{}
const App:FC>=()=>{// todo 定义state和义修改state的方法const [count,addCount]=useState(1);// todo 定义事件处理程序const add=()=>{addCount((n)=>n+1)}return
}
export default App;
案例四:定义修改对象
import Reac, { FC,useState} from "react";
interface IAppProps{}
interface IObj{name:string}
const App:FC>=()=>{const [obj,setObj]=useState>({})const giveObjName=()=>{// !! 下面的代码不能写 // obj.name = 'lakers';// setObj(obj);// todo1 写法1// setObj({name:'篮网'})// todo1 写法2obj.name='篮网'setObj({...obj})}return {obj.name}
}
案例五:定义修改数组
import React, { FC, useState } from "react";
interface IAppProps {}
interface IList {id: number;task: string;flag: boolean;
}
const App: FC> = () => {// todo 定义state和义修改state的方法const [list, setList] = useState[]>([]);// todo 定义事件处理程序const add = (e: any) => {if (e.keyCode === 13) {const obj = {id: list.length + 1,task: e.target.value,flag: false,};setList([obj, ...list]);e.target.value=''}};return ({list.map((item) => (- {item.task}
))}
);
};
export default App;
2.useReducer 定义和修改state
类似于类似 Redux 的功能
定义state以及修改state
可以理解为做出来类似vuex的效果
可以理解它是一个简易版本的状态管理工具
它接收一个如
(state, action) => newState的 reducer和一个初始化的state,并返回当前的 state 以及与其配套的dispatch方法作者:zidea
链接:https://www.jianshu.com/p/14e429e29798
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
写法一:
const [state,dispatch]=useReducer(reducer,initialState)
写法二:
const [state,dispatch]=useReducer((state,action)=>{},初始化的state)
案例:计数案例
流程 button --> add – dispatch发布 —> reducer的action接收 ----> state
import React, { FC, useReducer } from "react";interface IInitialState{count:number
}
const initialState:IInitialState={count:0
}
const reducer=(state:any,action:any) => {switch (action.type){case 'add':return {count:state.count+1}case 'jian': return {count: state.count - 1 }default:return initialState}
}const App:FC=() => {const [state,dispatch]=useReducer(reducer,initialState)const add=()=>{dispatch({type:'add'})}const jian=()=>{dispatch({type:'jian'})}return ({state.count}
)
}
export default App
3.useEffect
useEffect是用于实现生命周期功能的,他有3三种用法
语法:
语法: useEffect(callback,[数据])
数据:数据可以多个,可为props,state
**用法1:componentDidMount **
useEffect(() => {}, [])类似componentDidMount 钩子函数功能 :组件挂载结束
自动执行一次,可以进行真实DOM操作,数据请求发送
用法2:componentDidUpdate
useEffect(() => {}, [数据])类似componentDidUpdate钩子函数功能 :组件更新结束 表示对这个数据做监听
数据改变,就会触发,执行多次
**用法3:componentWillUnmount **
//callback的返回值为一个函数 useEffect(() => {return () => {} }) // 第二个参数随意类似componentWillUnmount 的功能 :组件销毁时触发
4.useLayoutEffect 类似useEffect
useLayoutEffect1. 用法和useEffect一致2. useLayoutEffect 解决了什么问题是useEffect解决不了的?- 其函数签名与 useEffect 相同,但它会在所有的 DOM 变更之后同步调用 effect。可以使用它来读取 DOM 布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect 内部的更新计划将被同步刷新 3. 理解- 范围不一致,useLayoutEffect的更大4. 什么时候用它?- 如果你正在将代码从 class 组件迁移到使用 Hook 的函数组件- 我们推荐你一开始先用 useEffect,只有当它出问题的时候再尝试使用 useLayoutEffect。
5.useRef ref绑定
通过ref绑定可以拿到类子组件的数据或方法
ref无法绑定函数子组件,但子组件使用forwardRef高阶组件可以解决
绑定类组件
// 父组件const 绑定名: any = useRef(null) //拿到子组件实例绑定名.current.数据/方法 //使用子组件的数据或方法<子组件 ref={绑定名}> //绑定子组件
绑定函数组件
ref无法绑定函数子组件,可以通过forwardRef高阶组件解决
- forwardRef
forwardRef 我们称之为 高阶组件[HOC] High Order Component
它是一个函数,接收一个组件作为参数,并返回一个新组件
高阶组件的原理是闭包
// 父组件绑定和使用如绑定类组件// 子组件导出时,导出新组件
export default React.forwardRef(Hello)
手动封装forwardRe
// 闭包
const HocComp = ( Comp: any ) => {return class _ extends React.Component{render () {return }}
}
6.usemperativeHandle
和ref绑定搭配,我们将子组件的内容绑定到父组件的ref中
-
搭配ref绑定来使用的
-
专用于函数组件
-
他有两个参数:第一个为ref,第二个为回调函数
-
它的返回值就是父组件ref绑定获得的结果
-
注意第一个参数ref的类型约定
// ref的类型约定
// ref: React.Ref
useImperativeHandle(ref,() => {return {可以返回数据或方法}
})
7.useContext 跨组件通信
创建上下文context对象
// src/context/index.ts
import React from 'react'const ctx = React.creatContext(0)export default ctx
数据源组件
import ctx from './context'....
return (<接收组件>
)
接收组件(类组件)
//引入上下文组件
import {useContext}
import ctx from './context'//从ctx拿到数据实例
static contextType=ctx;//使用数据
return({this.context}
)
接收组件(函数组件)
//引入上下问组件
import {useContext}
import ctx from './context'//从ctx拿到数据实例
const money=useContext(ctx)//使用数据
return({money}
)
8.useMeno 组件性能优化
问题一: 类组件中通过 shouldComponentUpdate 达到性能优化目的,那么函数组件呢?
解决: Hook ( useCallback useMemo )
问题二: 函数组件 - 重复渲染问题
因为函数组件本身是函数,所以只要数据改变,它就要重新执行自身总结
state的改变,会引起组件的重复调用,那么渲染就会重复执行,这样会带来性能损耗
解决: useMemo/useCallback
语法:
const memoValue =useMemo(()=>{当监听数据改变时,才执行这里的渲染代码},监听数据)
//该函数会得一个返回值,通常被称为记忆值
案例:优化函数组件的渲染
import React, { FC, useState,useMemo} from "react";const App:FC=()=>{const [n,setN]=useState(0)const [list,setList]=useState>([1,2,3,4])const add=()=>{setN((n)=>n+1)}const renderList=()=>{console.log('render');return list.map((item,index)=>( {item} ))}// memoValue为记忆值const memoValue= useMemo(() => renderList(), [list])const addList=()=>{setList([Math.max(...list)+1,...list])}return (
{memoValue}
)
}
export default App
9.useCallback 组件性能优化
父组件将渲染函数传递给子组件,但当父组件数据更新时,会引起子组件不必要的更新,所以可以使用useCallback得到一个返回值为渲染函数的记忆值,使用记忆值来代替传递的渲染函数
useCallback + memo【高阶组件】
// 父组件
import React, { FC, useState, useCallback } from "react";
import Hello from "./Hello";const App: FC = () => {const [count, setCount] = useState(0);const [list, setList] = useState>([1, 2, 3, 4]);const add = () => {setCount((n) => n + 1);};const renderList = () => {console.log('render')return list.map((item,index) => { item } )} // todo 得到一个记忆函数const memoFunc = useCallback(() => {return renderList()}, [list])return (
);
};export default App;// 子组件
import React, { ReactElement,memo } from 'react'interface Props {memoFunc: () => ReactElement[]
}function Hello({memoFunc}: Props): ReactElement {return ({ memoFunc() }
)
}export default memo(Hello)
10.useDebugValue 自定义Hook起名
给自定义Hook起名[ 谷歌调试插件显示 ]
自定义Hook就是一个封装函数
名字前缀 useXxx
注意: hook不可以嵌套使用
// 自定义Hook src/hooks/index.ts
import { useDebugValue, useEffect, useState } from "react";
const useDemo=(Flag:boolean)=>{const [txt,setText]=useState('');useEffect(()=>{Flag? setText('进入我心里') :setText('QNMD')},[])useDebugValue('Flag')return txt
}export {useDemo}
自定义Hook库:
- https://ahooks.js.org/zh-CN/
- https://github.com/Junscuzzy/useHooks.ts
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
