React Hook

React Hook

不编写class的情况下使用state等React特性

即将一些特性抽离进行模块化使用

所有可以在函数式组件中使用

useState  

 参数为初始值    返回当前state和更新state函数。

函数调用后变量消失,而state的变量会被React保留。

const [count, setCount] = useState(0); 初始state

<button onClick={() => setCount(count + 1)}>

可以直接使用声明的变量。替代this.state.<变量>

使用过程:

1.引入React中的useState Hook  可以存储内部state

2.调用useState声明state变量

返回数组([0] : 变量名,[1] : 更新变量函数)

3.使用更新函数传递一个新值,React会重新渲染组件,并把最新的值传递给该组件。

注意事项:和class中this.setState不同,useState是替换而不是合并。可以使用展开运算符达到合并更新对象。

setState(prevState => {
  // 也可以使用 Object.assign
  return {...prevState, ...updatedValues};
});

惰性初始state   在useState里传入函数返回一个初始值。此函数只会在初始渲染时被调用。

useEffect  

每次渲染之后都会执行副作用操作(数据获取,设置订阅,手动更新React组件中DOM)

类似于React class 生命周期中

componentDidMount, componentDidUpdate,  componentWillUnmount

的组合避免同一个生命周期包含不相关的逻辑,又把相关逻辑分离到不同的方法中。!!!按照代码用途分离他们。

effect的执行时机

useEffect会在浏览器完成布局和绘制之后,在一个延迟事件中被调用。

执行原理:告诉React组件渲染后执行哪些操作,React会保存你传递的函数(effect) ,执行DOM更新后再次调用effect。

!!!传递给useEffect的函数每次渲染都不同,effect获取最新的state变量。每次渲染都会生成一个新的effect,替换之前的effect。让effect成为渲染结果的一部分。

内部调用原因:利用JS闭包原理直接访问state变量,无需引入其他API。

清除effect:

effect返回一个函数,当执行清除操作时调用它。

执行当前effect时,对上一个effect进行清除。

为什么每次渲染都要执行effect:

避免class组件中没有处理更新逻辑导致bug

通过跳过Effect进行性能优化,class组件中使用componentDidUpdate 添加prevProps 或 prevState 比较逻辑解决。

useEffect(() => {

  document.title = `You clicked ${count} times`;

}, [count](依赖数组)); // 仅在 count 更改时更新

只运行一次effect(仅挂载和卸载时执行),传递一个空数组( [] ) 作为第二个参数。

Hook规则

不要再循环,条件或者嵌套函数中调用Hook。

确保总是在React函数的最顶层以及任何return之前调用。

React如何对应state和useState:

依赖与Hook调用的顺序,每次渲染Hook调用顺序都是相同的。

提取自定义Hook(复用)

使用Hook定义的一个函数,返回对应的值。!!!use开头。

useContext

const value  = useContext(MyContext)

!!!参数必须是context本身

原理:

当组件上一层最近的<MyContext.Provider>更新时,该Hook会触发重渲染,并使用最新传递给MyContext的 provider的context value值,

即使祖先使用React.memo 或 shouldComponentUpdate。

useContext(MyContext) 可以读取context的值以及订阅context的变化。仍然需要上层组件树使用<MyContext.Provider>为下层组件提供context。

 

useReducer

接受一个形如(state,aciton)=>newState 的reducer,并返回当前的state以及与其配套的dispatch方法。

  1. 适用于场景
  1. state逻辑较复杂且包含多个子值。
  2. 下一个state依赖前一个state。
  3. 对深更新进行优化,向子组件传递一个dispatch而不是一个回调函数。

使用方法:

声明reducer (state, action){switch(action.type)}(不同情况,分类处理)

初始化 const [sate, dispatch] = useReducer(reducer, initialState)

使用 dispatch({ type:’condition1’})

惰性初始化

将init函数作为useReducer的第三个参数传入。

init函数返回初始化对象。{count: initialCount}

useCallback

返回一个memoized回调函数(参数1:内联回调函数,参数2:依赖项参数)。

回调函数仅在依赖项改变时才会更新。可以优化使用引用相等性去避免非必要渲染。(例如shouldComponentUpdate的子组件)

useCallback(fn, deps) 相当于useMemo( () =>fn, deps)

!!!注意事项

依赖项数组不会作为参数传给回调函数。

useCallback 的真正目的还是在于缓存了每次渲染时 inline callback 的实例,这样方便配合上子组件的 shouldComponentUpdate 或者 React.memo 起到减少不必要的渲染的作用

useMemo

返回一个memoized值

const memoizedValue = useMemo(

() => computeExpensiveValue(a,b), [a, b]);创建函数,依赖项数组

依赖项发生改变时,重新计算memoized值。

优化:

避免每次渲染都进行高开销的计算。

没有设置依赖项数组,则每次渲染计算新值。

useRef

返回一个可变的ref对象,其 .current  属性初始化为传入参数。

返回ref对象在组件的整个生命周期内保持不变。

const refContainer = useRef(initalValue);

本质:

useRef就是在.current属性上保存一个可变值的”盒子”。

!!!ref对象内容发生改变时,useRef不会通知。变更.current属性不会引发重新渲染。如果想要在React绑定或解绑DOM节点的ref时运行代码,需要使用回调ref。

useImperativeHandle

使用ref时自定义暴露给父组件的实例值。

避免ref命令式代码。

useImperatveHandle(ref, createHandle, [deps])

useLayoutEffect

与useEffect相同,但它会在所有DOM变更之后同步调用efect。

使用它来读取DOM布局并同步触发重渲染。

!!!服务端渲染无法使用。将代码转移到useEffect中,或时将组件延迟到客户端渲染完成后显示。(useLayoutEffect执行前HTML都显示错乱)

服务端渲染HTML排除依赖布局组件使用showChild && <Child/>条件渲染。useEffect(() => {setShowChild(true);}, []) 延迟展示组件。

useDebugValue

useDebugValue(value)

可用与在React开发者工具中显示自定义hook标签

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值