likes
comments
collection
share

React Hooks 初识

作者站长头像
站长
· 阅读数 16

Hooks是React16 推出的一个功能:让函数组件具有类组件的能力。 Hooks 极大改变了 React 应用开发的模式和开发体验。

随着 hooks的使用,将来越来越多的组件将使用函数组件,而不再是class组件。Hooks代表着未来react开发的新趋势。

计数器demo

通过计数器的 demo 来学习hooks。

场景:

假设现在需要一个计数器组件,有一个本地的状态count,每隔1s,count增加1。

如果不使用hooks,按照之前的写法是:

import React from 'react';
​
class Counter extends React.Component {
    constructor() {
        super();
        this.state = {
            count: 10
        };
    }
    
    // 组件挂载后,设置定时器
    componentDidMount() {
        // 注意,定时器中的setState是同步的
        this.interval = setInterval(()=>{
            this.setState({count: this.state.count + 1})
        }, 1000)
    }
    
    // 在组件中使用了定时器,一定记得在组件卸载时,要清除定时器
    // 如果忘记清除了,那么在组件卸载后,这个定时器依旧存在,不仅消耗内存引起内存泄露,而且定时器还会调用setState的方法,但此时setState已经不存在了,所以会报错
    componentWillUnmount() {
        if(this.interval) {
            clearInterval(this.interval);
        }
    }
    render() {
        return <h3>{ this.state.count }</h3>
    }
}

或者,使用类属性新特性来声明状态:

import React from 'react';
​
class Counter extends React.Component {
   state = {
     count: 10
   }
    
    render() {
        return (
            <div>
                <h3>{ this.state.count }</h3>
            <button onClick={}>加1</button>
            </div>
        )
    }
}

以上的功能,在以前是无法在function组件中实现的,因为function组件没有state,没有生命周期

可是现在有了hooks,一切就不同了。

import React, { useState, useEffect } from 'react';
​
function Counter() {
    // useState声明一个state:count, 和更新state的方法:setCount
    // count的默认state是0
    const [count, setCount] = useState(0);
    
    // 组件挂载后,执行回调
    useEffect(() => {
        const interval = setInterval(() => {
            // c对应最新的state
            setCount(c => c + 1)
        }, 1000)
        
        // 组件卸载时,执行return的函数
        return () => clearInterval(interval)
    }, [])
    
    return <span>{count}</span>
}
​
export default Counter;

使用useState和useEffect,可以给function组件增加类似state和生命周期方法的效果。

使用useState声明状态,返回状态和更新状态的方法。

useEffect 方法,可以在组件更新完成之后,执行传入的回调,组件卸载时执行return的函数来做一些清理的工作。class组件有生命周期函数,function组件是没有生命周期函数的。可以使用useEffect 来模拟类组件的生命周期。

State Hokks有两个API:useState和useReducer。

useState其实是基于useReducer实现的一个API,useReducer才是react中基础的,关于状态管理的hook。

正如我们的经验,越底层的东西,使用越不简单,也越不常用。越上层的封装,使用越简单,也更常用。

所以,相比较useReducer,useState的使用频率更高,使用起来也更简单。

useState

通过useState传入默认值之后,返回一个数组,里面有两个变量(可以通过const res = useCount(0), 打印res来看看数组长什么样),一般都是通过数组解构,数组第一项作为一个state,第二项是更新该state的方法。比如,

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

注意点:

1.传入的默认值

2.setCount有两种用法:

setCount(1): 传入一个值:传入什么,state的值就变成什么。

setCount(c => c+1): 传入一个回调,回调函数的参数是当前最新的state,可以针对当前最新的state做些事情。

两种方式最大的区别是:

使用第一种方式,是直接覆盖的用法,参数中的state可能并不是最新的state,造成得不到我们想要的结果的情况。可能导致闭包陷阱。

使用第二种方式,回调函数的参数拿到是当前最新的state。可以规避闭包陷阱。

useReducer

useState其实是基于useReducer实现的hook,只不过会变得更加常用,使用方式更简单。

useReducer才是真正的基础的react 中关于状态管理的hook。

useReducer的用法很类似redux:

import React, { useReducer } from 'react';
​
// 定义Reducer函数,就像redux中定义reducer函数那样
// 接收一个state和action作为参数
function counterReducer(state, action) {
   switch(action.type) {
       case 'add':
           return state + 1;
       case 'minus':
           return state - 1;
       default:
           return state;
   } 
}
​
// 使用
function Counter() {
   // useReducer接收两个参数,第一个参数是reducer函数,第二个参数是初始的state
  // 返回一个数组,第一个参数是初始的state, 第二个参数是用来专门派发action的方法,只对当前的state生效
   const [ count, dispatchCounter ] = useReducer(counterReducer, 0);
    
    useEffect(() => {
        const interval = setInterval(() => {
    // dispatchCounter接收一个action作为参数
            dispatchCounter({type: 'add'})
        }, 1000)
        
        return () => clearInterval(interval)
    }, [])
  
  return (
    <span>{ count }</span>
  )
    
}

最后

React Hooks 改变了类组件的繁重的开发方式,提供了一种更简洁,轻便,灵活的开发体验,也是现今 React 的主流开发方式。