zf-6-redux typescript版本(30天)

redux 和 react-redux两个不同来讲的。

redux 就是一个状态的维护。
react-redux 则表示的是provider + ReactReduxContext + connect + context + redux
ps: ReactReduxContext 在 connect.js 和Context.js Provider.js 中都有使用
ps: react-redux会导出两个内容,一个Provider 另一个是 connect。

这两个重载之间没有任何分号之类的

在这里插入图片描述

interface 接口定义方法的话,是:
type 定义方法的 话,用=> 隔开。

在这里插入图片描述

必选参数不能放在可选参数的后边。 就是这里不能写= AnyAction的默认值,要不第二个参数不知道算谁的了。

在这里插入图片描述

这两种写法一样的

在这里插入图片描述

定义在哪里,在哪里使用的时候 传

在这里插入图片描述

bindActionCreators

使用的时候就是, onClick = { boundActions.increment }
在这里插入图片描述

??? extends中的继承又=是什么鬼。

在这里插入图片描述

父类引用子类,但是子类不能使用 父类的引用

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

connect-router-redux

在这里插入图片描述

为了保证全局history的唯一

在这里插入图片描述

外边引进来的CounterState的 另换个名字type Props = CounterState;

在这里插入图片描述

actions

在这里插入图片描述

打印,打印,打印,打印,打印,打印,打印,打印,打印
redux 和 react-redux两个不同来讲的。

redux 就是一个状态的维护。
react-redux 则表示的是provider + ReactReduxContext + connect + context + redux
ps: ReactReduxContext 在 connect.js 和Context.js Provider.js 中都有使用
ps: react-redux会导出两个内容,一个Provider 另一个是 connect。

react-redux

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Counter1 from './components/Counter1';
import Counter2 from './components/Counter2';
import store from './store';
import {Provider} from './react-redux';
ReactDOM.render(<Provider store={store}><Counter1/><hr/><Counter2/></Provider>,document.getElementById('root'));
src/components/Counter.js
import React, { Component } from 'react';
import actions from '../store/actions/counter1';
import {connect} from '../react-redux'
class Counter extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div>
                <p>{this.props.value}</p>
                <button onClick={this.props.increment}>+</button>
                <button onClick={this.props.decrement}>-</button>
            </div>
        )
    }
}

let mapStateToProps = state=>({value:state.counter});
export default connect(
    mapStateToProps,
    actions
)(Counter)
8.3 react-redux\index.js
import Provider from './Provider';
import connect from './connect';
export {
    Provider,
    connect
}
8.4 react-redux\Provider.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { ReactReduxContext } from './Context'
export default class Provider extends Component {
    static propTypes = {
        store: PropTypes.shape({
          subscribe: PropTypes.func.isRequired,
          dispatch: PropTypes.func.isRequired,
          getState: PropTypes.func.isRequired
        }),
        children: PropTypes.any
    }
    constructor(props) {
        super(props)
    }
    render() {
        return (
          <ReactReduxContext.Provider value={{store:this.props.store}}>
            {this.props.children}
          </ReactReduxContext.Provider>
        )
      }
}
8.5 react-redux\connect.js
import React from "react";
import { bindActionCreators } from "../redux";
import { ReactReduxContext } from "./Context";
export default function(mapStateToProps, mapDispatchToProps) {
  return function wrapWithConnect(WrappedComponent) {
    return class extends React.Component {
      static contextType = ReactReduxContext;
      constructor(props, context) {
        super(props);
        this.state = mapStateToProps(context.store.getState());
      }
      componentDidMount() {
        this.unsubscribe = this.context.store.subscribe(() =>
          this.setState(mapStateToProps(this.context.store.getState()))
        );
      }
      shouldComponentUpdate() {
        if (this.state === mapStateToProps(this.context.store.getState())) {
          return false;
        }
        return true;
      }
      componentWillUnmount() {
        this.unsubscribe();
      }
      render() {
        let actions = bindActionCreators(
          mapDispatchToProps,
          this.context.store.dispatch
        );
        return <WrappedComponent {...this.state} {...actions} />;
      }
    };
  };
}
8.6 react-redux\Context.js
import React from 'react'

export const ReactReduxContext = React.createContext(null)

export default ReactReduxContext
bindActionCreators.js
Counter.js
import React, { Component } from 'react';
import { createStore,bindActionCreators} from '../redux';
function reducer(state=0,action){
    switch(action.type){
        case 'INCREMENT':
            return state + 1;
        case 'DECREMENT':
            return state - 1;
        default:
            return state;
    }
}
const store = createStore(reducer,0);
function increment(){
   return {type:'INCREMENT'};
}
function decrement(){
   return {type:'DECREMENT'};
}
const actions = {increment,decrement};
//const boundIncrement = bindActionCreators(increment,store.dispatch);//可以传一个函数
const boundActions = bindActionCreators(actions,store.dispatch);//也可以传对象

export default class Counter extends Component {
    constructor(props) {
        super(props);
        this.state = { value: 0 };
    }
    componentDidMount() {
        this.unsubscribe = store.subscribe(() => this.setState({ value: store.getState() }));
    }
    componentWillUnmount() {
        this.unsubscribe();
    }
    render() {
        return (
            <div>
                <p>{this.state.value}</p>
                <button onClick={boundIncrement}>+</button>
                <button onClick={boundIncrement}>-</button>
            </div>
        )
    }
}
6.2 bindActionCreators.js
function bindActionCreator(actionCreator, dispatch) {
    return function() {
      return dispatch(actionCreator.apply(this, arguments))
    }
}
export default function bindActionCreators(actionCreators, dispatch) {
    if (typeof actionCreators === 'function') {
        return bindActionCreator(actionCreators, dispatch)
    }
    const boundActionCreators = {}
    for (const key in actionCreators) {
        const actionCreator = actionCreators[key]
        if (typeof actionCreator === 'function') {
            boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
        }
    }
    return boundActionCreators
}
7.3 combineReducers.js
export default function combineReducers(reducers) {
    const reducerKeys = Object.keys(reducers)
    return function combination(state = {}, action) {
        const nextState = {}
        for (let i = 0; i < reducerKeys.length; i++) {
            const key = reducerKeys[i];
            const reducer = reducers[key];
            const previousStateForKey = state[key];
            const nextStateForKey = reducer(previousStateForKey, action);
            nextState[key] = nextStateForKey;
        }
        return nextState;
    }
}
compose
function add1(str){
    return '1'+str;
}
function add2(str){
    return '2'+str;
}
function add3(str){
    return '3'+str;
}

function compose(...funcs){
    return funcs.reduce((a,b)=>(...args)=>a(b(...args)));
}
// 第一次返回  add3(add2(...args))
// 第二次返回  add3(add2(add1(...args)))
// 第三次返回  返回执行的结果

let result = compose(add3,add2,add1)('zhufeng');
console.log(result);
redux中间件
store\index.tsx
import { createStore, Store, AnyAction, Middleware, MiddlewareAPI, StoreEnhancer, StoreEnhancerStoreCreator, applyMiddleware } from '../redux';
import reducer from './reducers';
import { CombinedState } from './reducers';
//const store: Store<CombinedState, AnyAction> = createStore<CombinedState, AnyAction, {}, {}>(reducer, { counter1: { number: 0 }, counter2: { number: 0 } });
let logger: Middleware = (api: MiddlewareAPI) => (next: any) => (action: any) => {
    console.log(api.getState());
    next(action);
    console.log(api.getState());
    return action;
};
+let thunk: Middleware = (api: MiddlewareAPI) => (next: any) => (action: any) => {
+    if (typeof action == 'function') {
+        return action(api.dispatch, api.getState);
+    }
+    return next(action);
+};
+function isPromise(obj: any) {
+    return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
+}
+let promise: Middleware = (api: MiddlewareAPI) => (next: any) => (action: any) => {
+    return isPromise(action.payload)
+        ? action.payload
+            .then((result: any) => api.dispatch({ ...action, payload: result }))
+            .catch((error: any) => {
+                api.dispatch({ ...action, payload: error, error: true });
+                return Promise.reject(error);
+            })
+        : next(action);
+};
+let storeEnhancer: StoreEnhancer = applyMiddleware(thunk, promise, logger);
let storeEnhancerStoreCreator: StoreEnhancerStoreCreator = storeEnhancer(createStore);
let store: Store = storeEnhancerStoreCreator(reducer);
export default store;
3.5 applyMiddleware.tsx
import compose from './compose';
import { Middleware, Store, StoreEnhancer, Dispatch, MiddlewareAPI, StoreCreator, Action, AnyAction, Reducer } from './'
export function applyMiddleware(
    ...middlewares: Middleware[]
): StoreEnhancer
export default function applyMiddleware(
    ...middlewares: Middleware[]
): StoreEnhancer {
    return (createStore: StoreCreator) => <S, A extends Action>(
        reducer: Reducer<S, A>
    ): Store<S, A> => {
        const store = createStore(reducer)
        let dispatch: Dispatch;

        const middlewareAPI: MiddlewareAPI = {
            getState: store.getState,
            dispatch: (action) => dispatch(action)
        }
        const chain = middlewares.map(middleware => middleware(middlewareAPI))
        dispatch = compose(...chain)(store.dispatch)
        return {
            ...store,
            dispatch
        }
    }
}
actions\counter1.tsx
+import { AnyAction, Dispatch } from '../../redux';
const actions = {
    increment1(): AnyAction {
        return { type: types.INCREMENT1 };
    },
+    increment1Async() {
+        return function (dispatch: Dispatch) {
+            setTimeout(() => {
+                dispatch({ type: types.INCREMENT1 });
+            }, 1000);
+        }
+    },
+    increment1Promise() {
+        return {
+            type: types.INCREMENT1,
+            payload: new Promise((resolve: any, reject: any) => {
+                setTimeout(() => {
+                    let result = Math.random();
+                    if (result > .5) {
+                        resolve(result);
+                    } else {
+                        reject(result);
+                    }
+                }, 1000);
+            })
+        }
+    },
    decrement1(): AnyAction {
        return { type: types.DECREMENT1 };
    }
}
export default actions;
Counter1.tsx
import React, { Component } from 'react';
import actions from '../store/actions/counter1';
import { CombinedState } from '../store/reducers';
import { Counter1State } from '../store/reducers/counter1';
import { connect } from '../react-redux';
+import { ActionCreatorsMapObject, AnyAction } from '../redux';
type Props = Counter1State & typeof actions;
class Counter1 extends Component<Props> {
    render() {
        let { number, increment1, decrement1 } = this.props;
        return (
            <div>
                <p>{number}</p>
                <button onClick={increment1}>+</button>
+                <button onClick={this.props.increment1Async}>异步+1</button>
+                <button onClick={this.props.increment1Promise}>promise异步+1</button>
            </div>
        )
    }
}
let mapStateToProps = (state: CombinedState): Counter1State => state.counter1;
+export default connect<any>(
    mapStateToProps,
    actions
)(Counter1
connect-react-router 只学会使用,不考虑原理
2.9 Counter.tsx
Home.tsx
<button onClick={() => this.props.history.go(-1)}>返回</button>
Counter.tsx
import React, { Component } from 'react'
import { connect } from 'react-redux';
import actions from '../store/actions/counter';
import { CounterState } from '../store/reducers/counter';
import { RootState } from '../store/reducers';
type Props = CounterState & typeof actions;
class Counter extends Component<Props> {
    render() {
        return (
            <>
                <p>{this.props.number}</p>
                <button onClick={this.props.increment}>+</button>
                <button onClick={this.props.decrement}>-</button>
                <button onClick={() => this.props.go('/')}>Home</button>
            </>
        )
    }
}
let mapStateToProps = (state: RootState): CounterState => state.counter;
export default connect(
    mapStateToProps,
    actions
)(Counter);
actions
import * as types from '../action-types';
import { push } from '../../connected-react-router';
export default {
    increment() {
        return { type: types.INCREMENT }
    },
    decrement() {
        return { type: types.DECREMENT }
    },
    go(path: string) {
        return push(path);
    }
}
reducers\counter.tsx
import { AnyAction } from 'redux';
export interface CounterState {
    number: number
}
let initialState: CounterState = { number: 0 }
export default function (state: CounterState = initialState, action: AnyAction): CounterState {
    switch (action.type) {
        case types.INCREMENT:
            return { number: state.number + 1 };
        case types.DECREMENT:
            return { number: state.number - 1 };
        default:
            return state;
    }
}
src\history.tsx
import { createHashHistory } from 'history'
let history = createHashHistory();
export default history;

store\index.tsx
import { applyMiddleware, createStore } from 'redux'
import { routerMiddleware } from '../connected-react-router'
import history from '../history';
import reducers from './reducers';
const store = applyMiddleware(routerMiddleware(history))(createStore)(reducers);
export default store;

src\index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Link } from 'react-router-dom';
import Home from './components/Home';
import Counter from './components/Counter';
import { ConnectedRouter } from './connected-react-router'
import history from './history';
import store from './store';
import { Provider } from 'react-redux'
ReactDOM.render(
    <Provider store={store}>
        <ConnectedRouter history={history}>
            <>
                <Link to="/">Home</Link>
                <Link to="/counter">Counter</Link>
                <Route exact={true} path="/" component={Home} />
                <Route path="/counter" component={Counter} />
            </>
        </ConnectedRouter>
    </Provider>
    , document.getElementById('root'));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值