资讯专栏INFORMATION COLUMN

使用react hooks实现自己的context-redux

Jackwoo / 1682人阅读

摘要:首发自我的博客,欢迎注如要运行本文的代码,请先确认自己的版本已支持出来已经有段时间了,本文不对的具体用法作介绍,而是使用实现一个简易的基于的使用实现初版自带了供我们使用,它接受两个参数,一是函数,二是初始,并返回和函数,如下这个函数自己实现

首发自我的github博客,欢迎star

注:如要运行本文的代码,请先确认自己的react版本已支持hooks

react hooks出来已经有段时间了,本文不对hooks的具体用法作介绍,而是使用hooks实现一个简易的基于context的redux

使用useReducer实现初版redux

React hooks自带了useReducer供我们使用,它接受两个参数,一是reducer函数,二是初始state,并返回state和dispatch函数,如下

const [state, dispatch] = useReducer(reducer, initialState); 

这个函数自己实现的话也不难,如下:

const useMyReducer = (reducer, initialState) => {
    const [state, setState] = useState(initialState);
    const dispatch = action => {
        const newState = reducer(action, state);
        setState(newState);
    };
    return [state, dispatch];
};

即将initialState作为state的初始状态传入useState,dispatch则是一个函数,它会将接受的action和state传给reducer,并获取reducer的返回值赋给state

我们先利用useReducer实现一个计数器的简单页面

reducer函数和initialState如下:

const initialState = {
    count: 0
};

const reducer = (state, action) => {
    switch (action.type) {
        case "increase":
            return { ...state, count: state.count + 1 };
        case "decrease":
            return { ...state, count: state.count - 1 };
        default:
            return state;
    }
};

计数器组件:

const Demo = () => {
    const [state, dispatch] = useReducer(reducer, initialState); 
    return (
        
counter:{state.count}
); };

这就是初版的redux了,但这个redux有些问题,就是它的state和dispatch是属于自己的,其他组件并不能拿到,也就是说,如果我们的页面有两个Demo组件,它们的state是各自独立,互不影响的

将state和dispatch存在context中

为了解决上述问题,我们必须拥有一个全局状态,并将state和dispatch放入这个全局状态中。这里,我们选用context作为我们的全局状态,context在旧版React中不推荐使用,但在改进之后,官方开始推荐大家使用

我们先创建一个context:

const context = React.createContext();

为了各个组件都能拿到context的数据,我们需要有一个Provider组件包在最外层:

const Provider = props => {
    const [state, dispatch] = useReducer(reducer, initialState);
    return (
        
            {props.children}
        
    );
};

我们将useReducer返回的state、dispatch传入context.Provider中,让它的children都能拿到

然后,我们像下面一样用Provider包在组件外层:


    
    

我们删去计数器Demo组件中的:

const [state, dispatch] = useReducer(reducer, initialState); 

加上通过useContext函数拿到context上的数据:

const { state, dispatch } = useContext(context);

要注意的是,传入useContext函数的context必须是我们之前通过React.createContext()创建的context

这样,即使是两个Demo组件,它们也是共用一份数据了

解决异步的问题

很显然,现在的context-redux和单纯的redux一样,只能dispatch一个对象,也就是说,这个dispatch操作是同步的,如果我们要做异步的操作呢?很简单,我们借鉴redux-thunk的方法,让dispatch可以接受函数参数

改造Provider函数组件如下:

const Provider = props => {
    const [state, origin_dispatch] = useReducer(reducer, initialState);
    const dispatch = action => {
        if (typeof action === "function") {
            return action(origin_dispatch);
        }
        return origin_dispatch(action);
    };
    return (
        
            {props.children}
        
    );
};

我们将userReducer函数返回的原始dispath命名为origin_dispatch,自定义dispatch函数,当action为函数的时候,我们执行action函数,并将origin_dispatch当作参数传进去;action不是函数,直接调用origin_dispatch,不做处理

我们测试一下:

const sleep = wait => {
    return new Promise(resolve => {
        setTimeout(() => resolve(), wait);
    });
};
const increaseCount = async dispatch => {
    await sleep(1000);
    dispatch({ type: "increase" });
};

increaseCount是一个异步函数,我们将它当作参数传入我们封装的新dispatch中,点击increase按钮,1s之后,计数器的数字加1,至此,我们的context-redux也支持dispatch异步操作了

最后

本文的代码,我放在了自己的github上,这是传送门

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102246.html

相关文章

  • React Hook 不完全指南

    摘要:使用完成副作用操作,赋值给的函数会在组件渲染到屏幕之后。如此很容易产生,并且导致逻辑不一致。同时,这也是很多人将与状态管理库结合使用的原因之一。当我们通过的第二个数组类型参数,指明当前的依赖,就能避免不相关的执行开销了。 前言 本文内容大部分参考了 overreacted.io 博客一文,同时结合 React Hook 官方 文章,整理并归纳一些笔记和输出个人的一些理解 什么是 Hoo...

    Lin_R 评论0 收藏0
  • 精读《React Hooks

    摘要:更容易将组件的与状态分离。也就是只提供状态处理方法,不会持久化状态。大体思路是利用共享一份数据,作为的数据源。精读带来的约定函数必须以命名开头,因为这样才方便做检查,防止用判断包裹语句。前端精读帮你筛选靠谱的内容。 1 引言 React Hooks 是 React 16.7.0-alpha 版本推出的新特性,想尝试的同学安装此版本即可。 React Hooks 要解决的问题是状态共享,...

    kohoh_ 评论0 收藏0
  • 快速了解 React Hooks 原理

    摘要:使用该对象,可以跟踪属于组件的各种元数据位。调用你的组件这意味着它知道存储的元数据对象。下一次渲染会发生什么需要重新渲染组件由于之前已经看过这个组件,它已经有了元数据关联。 为了保证的可读性,本文采用意译而非直译。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 我们大部分 React 类组件可以保存状态,而函数组件不能? 并且类组件具有生命周期,而函数组件却不能...

    Hydrogen 评论0 收藏0
  • 【译】如何在React Hooks中获取数据?

    摘要:在这种情况下,如果状态发生变化,将再次运行以从获取数据。你可以在内做到在表单中获取数据到目前为止,我们只有和按钮的组合。现在,在获取数据时,可以使用向函数发送信息。例如,在成功请求的情况下,用于设置新状态对象的数据。 原文链接: https://www.robinwieruch.de/r... 在本教程中,我想通过state和effect hook来像你展示如何用React Hook...

    habren 评论0 收藏0
  • React函数式组件说到Hooks

    摘要:难道还不允许设计得对新人更友好了我们先把做成就是找骂啊这怎么怪到我们头上了事实是,即使在内部,也显然不是所有程序员都熟悉函数式编程的概念。 1.前言介绍 历史React在2013年开源,在2015引入函数式组件,不过在日常开发中经常被忽略。ReactJS Core Team 确实大部分成员都曾在推特上公开夸赞过对函数式编程 与 ML 系语言(或其特性)的优点:Sebastian 日常提...

    lavor 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<