React Hooks的使用——useContextuseReduceruseCallbackuseMemo解析

Posted 小小白学计算机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React Hooks的使用——useContextuseReduceruseCallbackuseMemo解析相关的知识,希望对你有一定的参考价值。

一、useContext的使用

在之前的开发中,我们要在组件中使用共享的Context有两种方式:

第一种方式:类组件可以通过 类名.contextType = MyContext方式,在类中获取context;

第二种方式:多个Context或者在函数式组件中通过 MyContext.Consumer 方式共享context;



但是多个Context共享时的方式会存在大量的嵌套:

import React, createContext, useState from 'react';
import CounterClass from './01-体验hooks/01-counter_class'
import CounterHook from './01-体验hooks/02-counter-hook'
import CounterHook2 from './01-体验hooks/03-counter-hook'
import MultiHookState from "./02-useState的使用/01-多个状态和复杂状态";
import ComplexHookState from './02-useState的使用/02-复杂状态的修改'
import ClassCounterChange from './03-useEffect的使用/01-class实现title的修改'
import HookCounterChange from './03-useEffect的使用/02-hook实现title的修改'
import EffectHookCancelDemo from './03-useEffect的使用/03-useEffect模拟订阅和取消订阅'
import MultiEffectHookDemo from './03-useEffect的使用/04-多个useEffect一起使用'
import ContextHookDemo from './04-useContext的使用/01-useContext的使用'
export const UserContext = createContext()
export const ThemeContext = createContext()
function App() 
    const [show, setShow] = useState(true)
    return (
        <div>
            /*<CounterClass />*/
            /*<CounterHook />*/
            /*<CounterHook2 />*/
            /*<MultiHookState />*/
            /*<ComplexHookState />*/
            /*<ClassCounterChange />*/
            /*<HookCounterChange />*/
            /*show && <EffectHookCancelDemo />*/
            /*<button onClick=e => setShow(!show)>切换</button>
            show && <MultiEffectHookDemo />*/
            <UserContext.Provider value=name: 'why', age: 18>
                <ThemeContext.Provider value=fontSize: "30px", color: "red">
                    <ContextHookDemo/>
                </ThemeContext.Provider>
            </UserContext.Provider>
        </div>
    )

export default App

import React from "react";
import UserContext, ThemeContext from "../App";
export default function ContextHookDemo() 
    return (
        <div>
            <UserContext.Consumer>
                
                    user => 
                        return (
                            <ThemeContext.Consumer>
                                
                                    theme => 
                                        return (
                                            <div>
                                                <div>用户昵称:user.name</div>
                                                <div>年龄:user.age</div>
                                                <h2>颜色:theme.color</h2>
                                            </div>
                                        )
                                    
                                
                            </ThemeContext.Consumer>
                        )
                    
                
            </UserContext.Consumer>
        </div>
    )


Context Hook允许我们通过Hook来直接获取某个Context的值;

注意事项:

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

二、useReducer

很多人看到useReducer的第一反应应该是redux的某个替代品,其实并不是。
useReducer仅仅是useState的一种替代方案:

  • 在某些场景下,如果state的处理逻辑比较复杂,我们可以通过useReducer来对其进行拆分;
  • 或者这次修改的state需要依赖之前的state时,也可以使用;
import React, useState, useReducer from "react";

function reducer(state, action) 
    switch (action.type) 
        case "increment":
            return ...state, counter: state.counter + 1
        case "decrement":
            return ...state, counter: state.counter - 1
        default:
            return state

    


export default function Home() 
    // const [count, setCount] = useState(0)
    const [state, dispatch] = useReducer(reducer, counter: 0)
    return (
        <div>
            <h2>Home当前计数:state.counter</h2>
            <button onClick=e => dispatch(type: "increment")>+1</button>
            <button onClick=e => dispatch(type: 'decrement')>-1</button>
        </div>
        /*<div>
            <h2>Home当前计数:count</h2>
            <button onClick=e => setCount(count + 1)>+1</button>
            <button onClick=e => setCount(count - 1)>-1</button>
        </div>*/
    )


数据是不会共享的,它们只是使用了相同的counterReducer的函数而已。
所以,useReducer只是useState的一种替代品,并不能替代Redux。

三、useCallback

useCallback实际的目的是为了进行性能的优化。
如何进行性能的优化呢?

  • useCallback会返回一个函数的 memoized(记忆的) 值;
  • 在依赖不变的情况下,多次定义的时候,返回的值是相同的;

案例一:使用useCallback和不使用useCallback定义一个函数是否会带来性能的优化;(答案:不能,因为两者都需要进行函数的创建国出)

案例二:使用useCallback和不使用useCallback定义一个函数传递给子组件是否会带来性能的优化;

以下为未使用useCallback的情况:

以下为使用useCallback的情况:

通常使用useCallback的目的是不希望子组件进行多次渲染,并不是为了函数进行缓存;

import React, memo, useCallback, useState from "react";

const HYButton = memo((props) => 
    console.log('HYButton重新渲染: ' + props.title)
    return <button onClick=props.increment> HYButton +1</button>
)
export default function CallbackHookDemo02() 
    console.log('CallbackHookDemo02重新渲染了')
    const [count, setCount] = useState(0)
    const [show, setShow] = useState(true)
    const increment1 = () => 
        console.log('执行increment函数')
        setCount(count + 1)
    
    const increment2 = useCallback(() => 
        console.log('执行increment函数')
        setCount(count + 1)
    , [count])
    return (
        <div>
            <h2>CallbackHookDemo02: count</h2>
            <HYButton title='btn1' increment=increment1 />
            <HYButton title='btn2' increment=increment2 />
            <button onClick=e => setShow(!show)>show切换</button>
            /*<button onClick=increment1>+1</button>
            <button onClick=increment2>+1</button>*/
        </div>
    )


四、useMemo

useMemo实际的目的也是为了进行性能的优化。
如何进行性能的优化呢?

  • useMemo返回的也是一个 memoized(记忆的) 值;
  • 在依赖不变的情况下,多次定义的时候,返回的值是相同的;

案例:

  • 案例一:进行大量的计算操作,是否有必须要每次渲染时都重新计算; (答案:每次渲染时都重新计算了)




import React, useMemo, useState from "react";

function calcNumber(count) 
    let total = 0
    for (let i = 1; i <= count; i++) 
        total += i
    
    console.log('for循环执行了')
    return total

export default function MemoHookDemo01() 
    const [count, setCount] = useState(10)
    const [show, setShow] = useState(true)
    const total = useMemo(() => 
        return calcNumber(count)
    , [count])
    return (
        <div>
            <h2>计算数字的累加和:total</h2>
            <button onClick=e => setCount(count + 1)>+1</button>
            <button onClick=e => setShow(!show)>show切换</button>
        </div>
    )


  • 案例二:对子组件传递相同内容的对象时,使用useMemo进行性能的优化



五、useMemo和useCallback的区别

以上是关于React Hooks的使用——useContextuseReduceruseCallbackuseMemo解析的主要内容,如果未能解决你的问题,请参考以下文章

react自定义hooks-自动改变页面的title,Http请求hooks等..(持续更新)

react---Hooks的基本使用---巷子

ReactReact全家桶React Hooks

ReactReact全家桶React Hooks

React 16.8发布:hooks终于来了!

使用 `react-apollo-hooks` 和 `useSubscription` 钩子