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 的功能

  1. 定义state以及修改state

  2. 可以理解为做出来类似vuex的效果

  3. 可以理解它是一个简易版本的状态管理工具

它接收一个如 (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中

  1. 搭配ref绑定来使用的

  2. 专用于函数组件

  3. 他有两个参数:第一个为ref,第二个为回调函数

  4. 它的返回值就是父组件ref绑定获得的结果

  5. 注意第一个参数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库:

    1. https://ahooks.js.org/zh-CN/
    2. https://github.com/Junscuzzy/useHooks.ts


    本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

    相关文章

    立即
    投稿

    微信公众账号

    微信扫一扫加关注

    返回
    顶部