美文网首页
React新特性,ReactHooks

React新特性,ReactHooks

作者: 番茄_tomatoMan | 来源:发表于2019-08-25 18:38 被阅读0次

    最新在学ReactHooks这个新特性,把学习笔记记下来,供大家分享。

    原先的函数组件是没有生命周期函数的,这样在使用函数组件时就会觉得没有类组件用的那么得心应手,在React16.9时,React官方出现了ReactHook这个语法糖,这个语法糖主要就是解决函数组件中没有生命周期函数的问题。

    一、useStates

    useState是让React函数组件能够使用state

    基本用法如下:

    const [ state, setState ] = useState( initState );

    1、state是你要设置的状态

    2、setState是你要更新状态的方法,命名随意

    3、initState为最初的state,可以是任意的数据类型,也可以是回调函数,但是必须有返回值

    二、useEffect

    数据获取、订阅、或手动修改React DOM这些行为都可以称之为副作用,useEffect正是用来处理这些副作用的。

    同时useEffect也是componentDidMount、componentDidUpdata、component WillUnMount这几个生命周期的统一。

    基本用法如下:

    useEffect( callback, array)

    1、callback回调函数用来处理副作用逻辑,另外可以返回一个函数用于清除工作,类似于componentWillUnMount

    2、array可选,一个数组,用来控制执行,当array为空数组时,在render之后执行,相当于componentDidMount,只执行一次,当没有array时,每次render触发后都会执行,当array内存在值时,会在数组发生改变后执行

    useEffect有两种清理机制

    React有两种副作用,一种是需要清理的,一种是不需要清理的。

    1、网络清除、DOM修改、日志记录等这些都是不需要清除的。useEffect会自动处理

    2、订阅和取消订阅,事件监听和取消事件监听,这种是需要清理的

    下面是useEffect清理机制:

    1、useEffect在每次执行之前都会自动清理之前的effect

    2、effect可以返回一个函数用于清理工作

    三、useContext

    useContext是为了方便我们使用context而提出的API

    context

    context是React提供数据共享的一种API,它可以解决需要通过多层嵌套传递props的问题。

    主要通过以下三种形式:

    1、通过React.createContext( )创建Context函数

    2、使用Context.Provider包裹组件,给他的后代组件提供数据

    3、Context.Provider所有的后代组件,都可以通过Context.Consumer获取Context的数据

    下面是context的一个使用案例:

    1、创建Context

    const context = React.creatContext( );

    2、使用Context.Provider包裹组件

    <Context.Provider value={store}>

        <MyComponent />

    </Context.Provider>

    3、使用Context.Consumer获取共享数据

    // MyComponent

    <Context.Consumer>

        {

            valve => {

                // value就是通过context共享过来的数据,这里是store        

        }}

    </ Context.Consumer>

    通过以上方法来使用context是非常麻烦的,所以hooks提供了useContext方法

    useContext( context )

    useContext( context )是针对context提供的一个API,它接受React.creatContext( )的返回值作为参数,也就是context的对象,并返回最近的context

    使用useContext将不再需要Previder和Consumer

    当最近的context更新时,那么使用该context的hook将会重新渲染

    基本使用

    const Context = React.creatContext( { loading: false, name: ‘jack’ } );

    const OnePage = ()=> {

        const ctx = useContext( Context );

        return (

            <div>

                { ctx.loading && ‘Loading...’ }

            </ div>

        )

    }

    四、useReducer 复杂的状态管理

    useReducer时useState的变体,用于处理复杂的状态管理

    useReducer可以作为useState的一种替代的方案,它的灵感来自于redux的reducer

    基本使用

    useReducer主要接受三个参数,下面是useReducer的基本用法:

    // useState的基本方法

    const [ state, setState ] = useState( initState );

    // useReducer的基本方法

    const [ state, dispatch ] = useReducer( reducer, initState, initialAction );

    参数:

    1、reducer是一个函数,用于处理action更新state

    2、initialState为初始的state

    3、initialAction为useReducer初始执行时被处理的action

    返回值:

    1、state为状态

    2、dispatch为更新state的方法,它接受action作为参数

    如何用useReducer更新state?

    只需要调用dispatch( action )方法即可更新state

    dispatch用于更新state,当dispatch( action )被调用时,reducer方法也会被调用,并会根据action的描述去更新state。

    reducer参数详解

    在了解参数reducer之前,我们先来了解action是什么:

    1、action

    action是一种动作的描述,描述你发出的这个动作它应该做的事。

    action本质是一个对象(object),它通常有一个type属性,用于描述该如何更新state,此外你还可以携带其他参数

    下面是action的一个例子:

    const action = {

        type:’ increment ’, // 增量表示该state的值要增加

        payload:{

            other:’ value ’ // 携带的其他参数

        }

    }

    我们该如何把描述性的action转化为最新的state?这就是reducer所做的事情了。

    2,reducer

    reducer是redux的产物,它本质上是一个函数,主要用于处理action,并它返回最新的state。

    总的来说,reducer是action和state的转换器,它根据action的描述,去更新state。

    它的结构如下:

    (state, action) => newState

    下面是reducer的一个应用案例:

    const initialState = { count: 0 }; // 初始state 

    const reducer = (state,action) =>{ 

        // 变量action,更加action的描述去更新state

        switch (action.type) {

        // 当type为reset时,重置state的值,让state等于初始state

        case 'reset': return initialState;

        // 当type为increment时,让count加一

        case 'increment': return {count: state.count + 1};

        // 当type为decrement时,让count减一

        case 'decrement': return {count: state.count - 1};

        // 当type不属于上面任何一个时,不做任何更改,返回当前的state

        default: return state;

        }

      }

    const MyCompoent = () =>{ 

        const [state, dispatch] = useReducer(reducer, initialState);

        return (

            

                

    当前count的值为:{ state.count }

                

    dispatch({ type: 'reset' }) } >重置

                

    dispatch({ type: 'increment' }) } >加一

                

    dispatch({ type: 'decrement' }) } >减一

        )

    }

    结合useContext

    useContext可以解决组件间的数据共享的问题,而useReducer则解决了复杂状态管理的问题,因此把他们结合起来之后,我们就可以实现redux的功能了。那也意味着我们可以不再依赖第三方状态管理器。

    五、额外的Hooks

    * useMemo

    * useCallback

    * useRef

    1、useMemo

    useMemo是一个用于性能优化的API,它通过记忆值手段让你避免在每个渲染上执行高开销的计算,可减少渲染的耗时。

    尤其适合用在需要复杂计算的场景,比如复杂的列表渲染,对象深拷贝等等。

    基本用法

    const memoizedValue = useMemo(callback,array);

    1,callback: 一个函数,用于处理你的计算逻辑。

    2,array: 一个数组,当数组发生改变时useMemo才会重新执行。

    useMemo的返回值是一个记忆值,它是callback的返回值。

    useMemo只会在数组发生变化时才会重新计算memoized(记忆)值。这样的优化有助于避免在每个渲染上进行昂贵的计算。

    下面是一个用例:

    // useMemo只会在obj1或obj2发生改变时才会重新执行。

    const obj1 = { id:"12", name:"jack" };const obj2 = { id:"14", name:"ben", age:23 };

    const memoizedValue = useMemo(()=>Object.assign(obj1,obj2),[obj1,obj2]);

    // 使用<div> { memoizedValue.name } </div>

    注意:不要在useMemo里面处理副作用的逻辑,副作用应该放在useEffect内处理。

    2、useCallback

    useCallback和useMemo一样,都是用于性能优化的API。

    基本用法

    const memoizedCallback = useCallback(callback,array);

    1,callback: 一个函数,用于处理你的计算逻辑。

    2,array: 一个数组,当数组发生改变时useCallback才会重新执行。

    useCallback 和 useMemo 类似,它们的返回值都是记忆化的。但是会有一些不同,useMemo的返回值就是callback的返回值,而useCallback的返回值则callback函数本身。

    useCallback(fn, inputs) 等价于 useMemo(() => fn, inputs)。

    下面是useCallback一个案例:

    const obj1 = { id:"12", name:"jack" };const obj2 = { id:"14", name:"ben", age:23 };

    const memoizedFn = useCallback(()=>Object.assign(obj1,obj2),[obj1,obj2]);  

    // 使用<div>{ memoizedFn().name }</div>

    它相当于useMemo的这种写法:

    const obj1 = { id:"12", name:"jack" };const obj2 = { id:"14", name:"ben", age:23 };

    const memoizedFn = useMemo(()=>{

        return ()=>{

            return Object.assign(obj1,obj2)

        }},[obj1,obj2]);  

    // 或const memoizedFn = useMemo(()=>()=>Object.assign(obj1,obj2),[obj1,obj2]);

    // 使用<div>{ memoizedFn().name }</div>

    3、useRef

    useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传递的参数(initialValue)。

    基本用法:

    const MyComponent = () =>{

        // 1,创建ref

        const inputEl = useRef(null);

        const onInput = () =>{

            // 3,访问ref

            console.log(inputEl.current.value)

        }

        // 2,挂载ref

        return (

            <div>

                <input ref={ inputEl } type="text" />

                <p>

                    <button onClick={ onInput } > 获取input的值 </button>

                </p>

            </div>

        )}

    六、自定义hooks

    自定义的hooks是一个 JavaScript 函数,其名称以 use 开头,函数内可以调用其他 Hook。

    主要就是利用react hooks封装成一个具有特定逻辑的,或可重用的函数。

    下面是官方的一个案例,查询指定用户是否在线:

    import { useState, useEffect } from 'react';

    function useFriendStatus(friendID) {

      const [isOnline, setIsOnline] = useState(null);

      function handleStatusChange(status) {

        setIsOnline(status.isOnline);

      }

      useEffect(() => {

        // 订阅

        ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);

        return () => {

          // 组件卸载时取消订阅

          ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);

        };

      });

      return isOnline;}

    案例应用:

    function FriendStatus(props) {

      const isOnline = useFriendStatus(props.friend.id);

      if (isOnline === null) {

        return 'Loading...';

      }

      return isOnline ? 'Online' : 'Offline';}

    七、hooks的规则

    Hooks 是 JavaScript 函数,但在使用它们时需要遵循一些规则。

    只在顶层调用Hooks

    尽量在顶层作用域中调用Hooks。

    不要在循环,条件或嵌套函数中调用Hook,否则可能会无法确保每次组件渲染时都以相同的顺序调用Hook。

    只在函数组件中调用Hooks

    React Hooks目前只支持函数组件,因此你不能在class组件中调用它API,但你可以在class组件内调用react hooks组件。

    下面是React Hooks的应用场景:

    1,函数组件

    2,自定义hooks (在自定义的hooks中调用hooks)

    在未来,react官方计划将React Hooks 拓展到class组件,到时候class组件也能使用React Hooks。

    相关文章

      网友评论

          本文标题:React新特性,ReactHooks

          本文链接:https://www.haomeiwen.com/subject/oqdkectx.html