博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
20行代码实现redux,50行代码实现react-redux
阅读量:4086 次
发布时间:2019-05-25

本文共 4387 字,大约阅读时间需要 14 分钟。

redux的简陋版实现

简单实现了下redux,帮助理解redux的原理:

// 维持应用的 state// 提供 getState() 方法获取 state// 提供 dispatch(action) 方法更新 state// 通过 subscribe(listener) 注册监听器// 通过 subscribe(listener) 返回的函数注销监听器// createStore参数为可变参数,第一个参数为reducer,第二个参数为初始stateexport function createStore(...arg){    let state = null;    let reducer = arg[0];    // 使用第二个参数为state初始化    if(arg.length > 1){state = arg[1]}    // 保存监听器的数据    let listeners = [];    let getState = () => state;    let subscribe = listener => listeners.push(listener)    let dispatch = (action) =>{        //执行reducer函数,更新状态        state = reducer(state,action)        //遍历listeners,执行之中的监听器函数        listeners.forEach(listener => listener())    }    return {        getState,        dispatch,        subscribe    }}

实现了redux的createStore方法,代码没几行,应该能看懂吧。

如何使用?

// import {createStore} from 'redux'import {createStore} from '../myredux'import reducer from './reducer'const initialState = {    counter:0,    title:'nihao'}const store = createStore(reducer,initialState)export default store;

把导入redux的代码换成myredux即可,其他使用和redux一样。当然,redux的中间件并没有实现。

react-redux简陋版实现

react-redux实现思路

版本一:

let Container = ({store}) => {    let [counter,setCounter] = useState(0);        useEffect(() =>{        store.subscribe(() => {            setCounter(store.getState().counter)        });    })    let add = () =>{        store.dispatch({            type:"INCREASE",            num:1        })    }    let min = () =>{        store.dispatch({            type:"DECREASE",            num:1        })    }    return  
}export default ({Consumer}) => (
{ (store) =>
}
)

使用

问题是, <Container/> 里面绑定了 <Counter/>

而且还需要把 <Consumer> 通过props传到 <Container/> 里。

并且 展示组件里也只能获取一个状态 counter

改进版

实现了 connect 函数,用法和 react-redux 基本一样,代码如下:

connect.js

import React,{createContext} from 'react';const {Provider,Consumer} = createContext();export const Container = ({store,children}) => {    return (        
{children}
)}class Inner extends React.Component{ constructor(props){ super(props) this.state = {} let {mapStateToProps,store} = this.props; //从mapStateToProps获得用户需要的状态 let mapState = mapStateToProps(store.getState()); for(let key in mapState){ this.state[key] = mapState[key] } } componentDidMount(){ let {store} = this.props //注册监听,这样当state发生改变时,改变Inner的内部状态,把这个新状态在render中传给了展示组件Comp,Comp就可以实时获取最新状态了 store.subscribe(()=>{ let storeState = store.getState(); for(let key in this.state){ this.setState({ [key]: storeState[key] }) } }) } render() { let {store,Comp,mapDispatchToProps} = this.props; let actions = mapDispatchToProps(store.dispatch) //把状态和方法传入到展示组件中 return (
) }}//connnect是一个高阶组价,返回一个函数,接受展示组件为参数,使用
包装,传入 storeexport const connect = (mapStateToProps,mapDispatchToProps) =>{ return (Comp) => { return () => (
{ (store) =>(
) }
) }}

如何使用:

使用方法,和 react-redux 基本上是一模一样的,只不过把 Provider 换成了 Container ,不过我完全可以叫 Provider ,一个名称而已。

在App.js:

import React from 'react';import './App.css';import store  from './store'import Cart from './components/Cart1'import {Container} from './connect.js'function App() {    return (        
);}export default App;

cart.js

import React from 'react'import {connect} from '../connect'let Counter = ({counter,title,min,add,changeTitle}) =>{    return (        

{counter}

{ title }

)}const mapStateToProps = (state) => { return { counter: state.counter, title:state.title }}const mapDispatchToProps = (dispatch) => { return { add: () => { dispatch({type:"INCREASE",num:1}) }, min: () => { dispatch({type:"DECREASE",num:1}) }, changeTitle() { dispatch({type:"UPDATE_TITLE"}) } }}export default connect(mapStateToProps,mapDispatchToProps)(Counter);

已经可以和 react-redux 完全一样的用法。

当然,这里的实现只是为了帮助理解 react-redux 内部是如何实现,并不一定是最好用的,实际工作中直接使用 react-redux 就好了。

源码

代码放在Github上了,欢迎star: 

转载地址:http://pvqni.baihongyu.com/

你可能感兴趣的文章
restassured - JsonPath
查看>>
(eden)eggs
查看>>
理解字节序 [Understanding Big and Little Endian Byte Order]
查看>>
细说WebSocket -- Node.js篇
查看>>
redis
查看>>
UML类图几种关系的总结
查看>>
【动态规划】回文子序列个数
查看>>
模线性同余方程组求解
查看>>
Path Cover (路径覆盖)
查看>>
Codeforces-5C. Longest Regular Bracket Sequence
查看>>
javascript 单行向上滚动文字
查看>>
Vue+element UI实现分页组件
查看>>
hadoop问题锦集(一):mapreduce不能在集群中运行
查看>>
JS判断数组是否包含某元素
查看>>
cxf-rs 、spring 和 swagger 环境配置切换【github 有项目】
查看>>
[LeetCode] Palindrome Number
查看>>
struts2 自定义类型转换器
查看>>
python中使用xlrd、xlwt操作excel表格详解【转】
查看>>
Node.js(day6)
查看>>
CAFFE学习笔记(二)Caffe_Example之测试mnist
查看>>