美文网首页
使用useReducer和Context替代redux

使用useReducer和Context替代redux

作者: percykuang | 来源:发表于2020-07-24 21:48 被阅读0次

使用useReducer和Context替代redux

步骤:

  1. 将数据集中在一个store对象
  2. 将所有操作集中在reducer
  3. 创建一个Context
  4. 创建对数据的读写API
  5. 将第4步的内容放到第3步的Context
  6. 用Context.Provider将Context提供给所有组件
  7. 各个组件用useContext获取读写API

代码演示:

import React, { Dispatch, useEffect, useContext, createContext, useReducer } from 'react'
import './App.css'

interface IPersonState {
  books: string[]
  movies: string[]
}

type IPersonAction = {
  type: 'getBooks' | 'getMovies'
  payload: string[]
}

const initialState: IPersonState = {
  books: [],
  movies: [],
}

function reducer(state: IPersonState = initialState, action: IPersonAction) {
  if (action.type === 'getBooks') {
    return { ...state, books: action.payload }
  }
  if (action.type === 'getMovies') {
    return { ...state, movies: action.payload }
  }
  return state
}

export interface IContextValue {
  state: IPersonState
  dispatch: Dispatch<IPersonAction>
}

const Context = createContext<IContextValue | undefined>(undefined)

function Person() {
  const [state, dispatch] = useReducer(reducer, initialState)

  return (
    <Context.Provider value={{ state, dispatch }}>
      <div>
        <Books />
        <Movies />
      </div>
    </Context.Provider>
  )
}

function Books() {
  const { state, dispatch } = useContext(Context)!
  useEffect(() => {
    fetch('http://api.kuanglinfeng.com')
      .then((response) => response.json())
      .then((data) => dispatch({ type: 'getBooks', payload: data.books }))
  }, [])

  return (
    <div>
      <h1>我的书籍</h1>
      <ul>
        {state.books!.map((book) => (
          <li key={book}>{book}</li>
        ))}
      </ul>
    </div>
  )
}

function Movies() {
  const { state, dispatch } = useContext(Context)!

  useEffect(() => {
    fetch('http://api.kuanglinfeng.com')
      .then((response) => response.json())
      .then((data) => dispatch({ type: 'getMovies', payload: data.movies }))
  }, [])
  return (
    <div>
      <h1>我的电影</h1>
      {state.movies.map((movie) => (
        <li key={movie}>{movie}</li>
      ))}
    </div>
  )
}

function App() {
  return (
    <div className="App">
      <Person />
    </div>
  )
}

export default App

如何对reducer进行拆分?

答:可将reducer写成多个对象的形式,合并所有的子reducer时只需要{...reducer1, ...reducer2, ...}即可

相关文章

网友评论

      本文标题:使用useReducer和Context替代redux

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