Skip to content

如何用 hooks 实现一个 Redux ​

本节目标:理解“如何用 hooks 实现一个 Redux”的核心思路,并能把它用于实际开发或面试表达。 ==上一章我们留下了一道思考题,让组件切换时能够保存当前组件的状态。当组件切换后,当前组件即被卸载,对于组件内部有关的函数引用也会消失,作用域引用消失,闭包变量不复存在。== ==所以通过该组件内部缓存是行不通的,必须采取状态存储在组件外的方式。== ==也许你马上就想到了== redux==,这当然可以,但如果真要用这个,我也就没有说的必要了。== ==其实也是为了拓展一下大家的思路,全局的状态管理不仅仅可以用== redux==,==react hooks ==同样可以模拟出这种功能。现在我们就用== hooks ==中的== useContext ==结合== useReducer ==打造出类似== redux ==的状态管理功能。== 用 hooks 写一个简单的 redux ==在== Singers ==目录下新建一个文件== data.js, ==模拟一个简单的== redux ==代码如下:==

import React, {createContext, useReducer} from 'react';
import { fromJS } from 'immutable';
export const CategoryDataContext = createContext({});
export const CHANGE_CATEGORY = 'singers/CHANGE_CATEGORY';
export const CHANGE_ALPHA = 'singers/CHANGE_ALPHA';
const reducer = (state, action) => {
  switch(action.type) {
    case CHANGE_CATEGORY:
      return state.set('category', action.data);
    case CHANGE_ALPHA:
      return state.set('alpha', action.data);
    default:
      return state;
  }
};
export const Data = props => {
  const [data, dispatch] = useReducer(reducer, fromJS({
    category: '',
    alpha: ''
  }));
  return (
    <CategoryDataContext.Provider value={{data, dispatch}}>
      {props.children}
    </CategoryDataContext.Provider>
  )
}

==然后,在== App.js ==中用== Data ==这个== Provider ==组件来包裹下面的子组件==

:
//App.js//

==增加引入代码==

import { Data } from './application/Singers/data';
function App () {  return (    <Provider store={store}>      <HashRouter>        <GlobalStyle></GlobalStyle>        <IconStyle></IconStyle>        <Data>          { renderRoutes (routes) }        </Data>      </HashRouter>    </Provider>  )}

==然后在== Singers/index.js ==来运用:== // ==首先需要引入==

 useContext//

==将之前的== useState ==代码删除==

const {data, dispatch} = useContext (CategoryDataContext);//

==拿到== category ==和== alpha ==的值==

const {category, alpha} = data.toJS ();

==而且== handleUpdatexxx ==函数也要修改==

:
//CHANGE_ALPHA

==和== CHANGE_CATEGORY ==变量需要从== data.js ==中引入==

let handleUpdateAlpha = (val) => {  dispatch ({type: CHANGE_ALPHA, data: val});  updateDispatch (category, val);};
let handleUpdateCatetory = (val) => {  dispatch ({type: CHANGE_CATEGORY, data: val});  updateDispatch (val, alpha);};

==至此,一个比较简单的== redux ==就用== hooks ==实现完成了。== ==看到这里,你可能会说,==hooks ==现在不就可以取代== redux ==吗?== ==现在的确也有不少人这样说,尽管== hooks ==能模拟== redux ==的核心功能,但是能够取代== redux ==这件事我不敢苟同。==

  1. ==首先== redux ==有非常成熟的状态跟踪调试工具,也就是== chrome ==浏览器的== redux-devtools ==插件,至少到现在为止开发中很多的错误我都是通过它发现的。换而言之,它能够协助我们写出更利于维护的代码,并且在出现故障时快速找到问题的根源。==
  2. ==其次,==redux ==有非常成熟的数据模块化方案,不同模块的== reducer ==直接导出,在全局的== store ==中,调一下== redux ==自带的== combineReducer ==即可,目前从官方的角度看== hooks ==这方面并不成熟。==
  3. Redux ==拥有成熟且强大的中间件功能,如== redux-logger, redux-thunk, redux-saga==,用== hooks ==实现中间件的功能就只能靠自己手动实现了。==

==当然== redux ==也并不是十全十美的,有些方面也经常被人吐槽,比如繁重的模板代码,需要== react-redux ==引入徒增项目包大小等等。但是瑕不掩瑜,这些不妨碍我们使用== redux ==开发出容易调试并维护的应用。== ==因此客观来说,==redux ==是一个短时间不可被替代的状态管理方案。== 歌手列表页的数据缓存 ==有了分类名称的缓存,我们再来做歌手列表页的数据缓存就轻松多了。== //useEffect ==中增加判断逻辑==

useEffect (() => {  if (!singerList.size) {    getHotSingerDispatch ();  }}, []);

==当歌手列表不为空时,就不发== Ajax ==请求,同时能够记忆之前的分类,让分类和列表对应,正是我们想要的效果。== > 来自

 <https://juejin.im/book/5da96626e51d4524ba0fd237/section/5da976d9e51d45249246ef40>

本站总访问 — 次