Hooks 是一项新功能提案,可以在不编写类的情况下使用 state(状态) 和其他 React 功能。

useState

import React, { useState } from 'react';

function Test() {
    const [count, setCount] = useState(0)
    const [username, setUsername] = useState('布丁')
    const [age] = useState(17)

    return (
        <div>
            <p>姓名:{username}</p>
            <p>年龄:{age}</p>
            <p>数字:{count}</p>

            <button onClick={() => {
                setCount(count + 1)
            }}>点击数字+1</button>

            <button onClick={() => {
                setCount(count - 1)
            }}>点击数字-1</button>
        </div>
    )
}


export default Test;

语法:const [state, setState] = useState(initialState);

  • 传入唯一的参数: initialState,可以是数字,字符串等,也可以是对象或者数组。
  • 返回的是包含两个元素的数组:第一个元素,state 变量,setState 修改 state值的方法。

与在类中使用 setState 的异同点:

  • 相同点:也是异步的,例如在 onClick 事件中,调用两次 setState,数据只改变一次。
  • 不同点:类中的 setState 是合并,而函数组件中的 setState 是替换

useEffect

useEffect增加了从函数式组件执行副作用的功能。它与 React 类中的 componentDidMount,componentDidUpdate,和 componentWillUnmount 有相同的功能,但是统一为单个 API。(相当于这三个生命周期的组合)

import React, { useState, useEffect } from 'react';

function Test() {
    const [count, setCount] = useState(0)
    const [username, setUsername] = useState('布丁')
    const [age] = useState(17)

    useEffect(() => {
       console.log(count,age)
    })

    return (
        <div>
            <p>姓名:{username}</p>
            <p>年龄:{age}</p>
            <p>数字:{count}</p>

            <button onClick={() => {
                setCount(count + 1)
            }}>点击数字+1</button>

            <button onClick={() => {
                setCount(count - 1)
            }}>点击数字-1</button>
        </div>
    )
}


export default Test;

语法:useEffect(didUpdate);
有两个参数:
第一个参数是一个函数,是在第一次渲染以及之后更新渲染之后会进行的副作用。
这个函数可能会有返回值,倘若有返回值,返回值也必须是一个函数,会在组件被销毁时执行。

第二个参数为可选参数:

  1. 当什么都不传的时候,则每次更新都会执行。(相当于componentDidMount,componentDidUpdate)。
  2. 当传的参数是一个空数组[ ]时,则useEffect只执行一次。告诉 React 你的 effect 不依赖于组件中的任何值,仅在组件挂载和卸载时执行,从不在更新时运行。
useEffect(() => {
        console.log(count)
    }, [])
  1. 当传的参数是state中的数据的数组时[age,count],则每次数组当中的数据发生变化时useEffect才执行。
useEffect(() => {
        console.log(count)
    }, [count])

useReducer

语法:const [state, dispatch] = useReducer(reducer, initialArg, init);

useState 的替代方案。 接受类型为 (state, action) => newState 的reducer,并返回与 dispatch 方法配对的当前状态。

import React, { useState, useEffect, useReducer } from 'react';

const initState = { count: 0 }

function reducer(state, action) {
    switch (action.type) {
        case 'add':
            return { count: state.count + 1 };
        case 'minus':
            return { count: state.count - 1 };
        case 'reset':
            return initState;
        default:
            return state
    }
}

function Test() {
    // const [count, setCount] = useState(0)
    // const [username, setUsername] = useState('布丁')
    // const [age] = useState(17)

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

    useEffect(() => {
        console.log(state.count)
    }, [state.count])

    return (
        <div>
            {/* <p>姓名:{username}</p>
            <p>年龄:{age}</p> */}
            <p>数字:{state.count}</p>

            <button onClick={() => {
                dispatch({
                    type: 'add'
                })
            }}>点击数字+1</button>

            <button onClick={() => {
                dispatch({
                    type: 'minus'
                })
            }}>点击数字-1</button>

            <button onClick={() => {
                dispatch({
                    type: 'reset'
                })
            }}>重置</button>
        </div>
    )
}


export default Test;

useReducer 接受可选的第三个参数 initialAction 。如果提供,则在初始渲染期间应用初始操作。这对于计算包含通过 props(属性) 传递的值的初始 state(状态) 非常有用

import React, { useState, useEffect, useReducer } from 'react';

//const initState = { count: 0 }

function init(initialCount) {
    return { count: initialCount };
}


function reducer(state, action) {
    switch (action.type) {
        case 'add':
            return { count: state.count + 1 };
        case 'minus':
            return { count: state.count - 1 };
        case 'reset':
            return init(action.payload);
        default:
            return state
    }
}

function Test({initialCount = 0}) {
    // const [count, setCount] = useState(0)
    // const [username, setUsername] = useState('布丁')
    // const [age] = useState(17)

    const [state, dispatch] = useReducer(reducer, initialCount,init)

    useEffect(() => {
        console.log(state.count)
    }, [state.count])

    return (
        <div>
            {/* <p>姓名:{username}</p>
            <p>年龄:{age}</p> */}
            <p>数字:{state.count}</p>

            <button onClick={() => {
                dispatch({
                    type: 'add'
                })
            }}>点击数字+1</button>

            <button onClick={() => {
                dispatch({
                    type: 'minus'
                })
            }}>点击数字-1</button>

            <button onClick={() => {
                dispatch({
                    type: 'reset',
                    payload: initialCount
                })
            }}>重置</button>
        </div>
    )
}


export default Test;