20行代码实现redux,50行代码实现react-redux

timg (1).jpeg

redux的简陋版实现

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

// 维持应用的 state
// 提供 getState() 方法获取 state
// 提供 dispatch(action) 方法更新 state
// 通过 subscribe(listener) 注册监听器
// 通过 subscribe(listener) 返回的函数注销监听器
// createStore参数为可变参数,第一个参数为reducer,第二个参数为初始state
export 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实现思路
借助于context,把store通过Provider实现共享,这样,在Provider内部的子组件就可以获得store,然后在内部组件,需要获取状态的地方,使用consumer包装,获得store,就可以实现状态共享了。

版本一:

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) => }
    
    )

使用


    
    


问题是,里面绑定了
而且还需要把通过props传到里。
并且 展示组件里也只能获取一个状态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是一个高阶组价,返回一个函数,接受展示组件为参数,使用包装,传入 store export 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: https://github.com/cooleye/connect.js

你可能感兴趣的:(20行代码实现redux,50行代码实现react-redux)