使用useReducer和useContext管理组件

useReducer

useState可以用最简单的方式更新状态,但是状态更新的逻辑散落在UI中,不能独立复用,也不便于测试。使用useReducer来对一个组件的状态进行管理就可以避免这一情况。

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

const initialState = []

const reducer = (state, action) => {
  const [type, value] = action
  const copy = [...state]
  switch (type) {
    case 'add':
      copy.push(value)
      return copy
    case 'del':
      copy.splice(value, 1)
      return copy
    default:
      return copy;
  }
}

export default TodoList = () => {
  const [state, dispatch] = useReducer(reducer, initialState)
  const [value, setValue] = useState('')

  return (
    <div>
      <h2>list</h2>
      <input type="text" onBlur={(e) => setValue(e.target.value)} />
      <button onClick={() => dispatch(['add', value])}>+</button>
      <ul>
        {
          state.map((item, index) => (
            <li key={index}>
              <span>{index + 1}:{item}</span>
              <button onClick={() => dispatch(['del', index])}>-</button>
            </li>
          ))
        }
      </ul>
    </div>
  )
}

这样我们就完成了一个简单的TodoList组件
在这里插入图片描述

useContext
useReducer虽然很好地分离了逻辑和UI,但是无法像redux一样进行跨组件的状态共享,在某些情况下如如果组件的状态都使用redux进行管理会导致redux比较混乱,所以针对比较复杂的组件我们使用useContext来实现跨组件的状态共享可以很好的避免这些情况。

//index
import React, { useReducer } from 'react'
import Input from './input'
import List from './list'

export const TodoContext = React.createContext({})

const initialState = []

const reducer = (state, action) => {
  const [type, value] = action
  const copy = [...state]
  switch (type) {
    case 'add':
      copy.push(value)
      return copy
    case 'del':
      copy.splice(value, 1)
      return copy
    default:
      return state;
  }
}

export default () => {
  const [state, dispatch] = useReducer(reducer, initialState)
  return (
    <div>
      <h2>list</h2>
      <p>Number:{state.length}</p>
      //在顶层组件中下发state和dispatch
      <TodoContext.Provider value={{ state, dispatch }}>
        <Input />
        <List />
      </TodoContext.Provider>
    </div>
  )
}

//input
import React, { useContext, useState } from 'react'
import {TodoContext} from './index'
export default  () => {
  //下层组件使用useContext获取顶层组件下发的state和dispatch
  const {dispatch} = useContext(TodoContext)
  const [value, setvalue] = useState('')
  return (
    <div>
      <input type="text" onBlur={(e) => setvalue(e.target.value)} />
      <button onClick={() => dispatch(['add', value])}>+</button>
    </div>
  )
}

//list
import React, { useContext } from 'react'
import Todo from './todo'
import { TodoContext } from './index'

export default () => {
//下层组件使用useContext获取顶层组件下发的state和dispatch
  const { state } = useContext(TodoContext)
  return (
    <ul>
      {
        state.map((item, index) => <Todo item={item} index={index} key={index} />)
      }
    </ul>
  )
}
//todo
import React, { useContext } from 'react'
import { TodoContext } from './index'
export default  ({ index, item }) => {
  //下层组件使用useContext获取顶层组件下发的state和dispatch
  const {dispatch} = useContext(TodoContext)
  return (
    <li key={index}>
      <span>{index + 1}:{item}</span>
      <button onClick={() => dispatch(['del', index])}>-</button>
    </li>
  )
}

在组件顶层使用useReducer统一管理状态和逻辑,下层组件只负责UI部分,这样组件的状态管理就变得很清晰了。每一个组件都会有一套内部的状态管理,组件注销时该组件的状态也就注销了,不会像redux一样没有使用的状态也依然存在无法注销。

原文链接:https://blog.csdn.net/qq_41739983/article/details/117442184

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值