React Hooks数据管理

1,197 阅读3分钟

什么是React Hook

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性,以及数据状态共享。

本文仅用于学习过程中记录!!!

useState介绍

useState是react自带的一个hook函数,作用是用来声明状态变量

function Example() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => {setCount(count+1)}}>Click me</button>
    </div>
  )
}

useEffect介绍

useEffect代替常用生命周期函数,useEffect跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API,可以比喻为它使得函数组件拥有了“生命周期函数”。

function Example() {
  const [count, setCount] = useState(0)
  useEffect(() => {
    console.log(`useEffect => You cliked ${count}`)
    return () => {
      console.log('==============')
    }
  }, [count])
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => {setCount(count+1)}}>Click me</button>
    </div>
  )
}
  • 在useEffect第二个参数为空时,视图每次render都会重新执行useEffect的内容,设置为[]的时候,只有首次会被渲染,设置[count]的时候,在count发生变化才执行useEffect
  • 在useEffect中第二个参数设置为[],并且return一个函数,可以实现componentWillUnmount

useContext介绍

useContext可以帮助我们跨越组件层级直接传递变量,实现共享,避免一层层的传递状态。

它对所包含的组件树提供全局共享数据的

const CountContext = createContext()

function Counter() {
  let count = useContext(CountContext)
  return (<h2>{count}</h2>)
}

function Example() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => {setCount(count+1)}}>Click me</button>
      <CountContext.Provider value={count}>
        <Counter></Counter>
      </CountContext.Provider>
    </div>
  )
}

useReducer介绍

useReducer可以看做是对 useState 做了一层包装,让我们可以更直观的去管理状态。看下它的使用方法:

function ReducerDemo() {
  const [count, dispatch] = useReducer((state, action) => {
    switch(action.type) {
      case 'add':
        return state+1
      case 'sub':
        return state-1
      default:
        return state
    }
  }, 0)
  return (
    <div>
      <h2>现在计数是:{count}</h2>
      <button onClick={() => {dispatch({
        type: 'add'
      })}}>Increment</button>
      <button onClick={() => {dispatch({
        type: 'sub'
      })}}>Dcrement</button>
    </div>
  )
}

使用useContext和useReducer实现数据管理

新建一个reducer,初始化数据、添加数据处理逻辑,通过useContext包裹组件,使得被包裹的组件可以获取数据和dispatch,共享数据为了组件树能获取数据,共享dispatch让组件树可以修改数据状态信息

import React, { createContext, useReducer } from 'react';
export const CounterContext = createContext({})
export const ADD_COUNTER = 'ADD_COUNTER'
export const DELETE_COUNTER= 'DELETE_COUNTER'

const reducer = (state, action) => {
  switch(action.type) {
    case ADD_COUNTER:
      return action.count + 1
    case DELETE_COUNTER:
      return action.count - 1
    default: 
      return state
  }
}

export const Counter = props => {
  const [count, dispatch] = useReducer(reducer, 0)

  return (
    <CounterContext.Provider value={{
      count, dispatch
    }}>
      {props.children}
    </CounterContext.Provider>
  )
}

ShowData组件和ChangeData组件包裹在Counter内部,因此可以通过useContext获取到父组件的数据以及dispatch,然后通过dispatch去更新状态数据信息

import React, {useContext} from 'react'
import { Counter, CounterContext, ADD_COUNTER, DELETE_COUNTER } from './counter'

function Example() {
  return (
    <div>
      <Counter>
        <ShowData></ShowData>
        <ChangeData></ChangeData>
      </Counter>
    </div>
  )
}

function ShowData() {
  const { count } = useContext(CounterContext)
  return (
    <div>
      当前计数: {count}
    </div>
  )
}

function ChangeData() {
  const { count, dispatch } = useContext(CounterContext)
  return (
    <div>
      <button onClick={() => {dispatch({
        type: ADD_COUNTER,
        count: count
      })}}>增加</button>
      <button onClick={() => {
        dispatch({
          type: DELETE_COUNTER,
          count: count
        })
      }}>减少</button>
    </div>
  )
}

export default Example

通过这些就实现了类Redux的效果以达到数据管理的目的