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/co...
,