为了账号安全,请及时绑定邮箱和手机立即绑定

快速上手React+TypeScript+Redux技术栈

标签:
React.JS

2018年的六一儿童节已到,特此一篇来献给小盆友们。此处应该有掌声....


webp

明猪不装暗逼.png

写在前面:
首先,什么是TypeScript?
官方原话:TypeScript is a typed superset of JavaScript that complies to plain JavaScript. Any host. Any OS. Open source.
TypeScript是JavaScript类型的超集(强类型版本),它可以编译成纯的JavaScript,它可以再任何浏览器,任何计算机和任何操作系统上运行,并且开源。
嗯,是的,你可以理解为TypeScript硬是把JavaScript(弱类型语言)"掰弯"了,变成强类型语言;强类语言的优势在于静态类型的检查,TypeScript虽然是强类型的语言,但是如果对象被声明为any类型,就会忽略所有的类型检查。这种灵活的结构保证了它整体有强类语言检查优势的同时,在一些细节问题上保持了弱类型的灵活。

1.为了能够快速搭建应用,我们将使用create-react-app官方脚手架为基础进行扩展。
创建一个项目(TypeScript版本)

 npx create-react-app 应用名称 --scripts-version=react-scripts-ts

2.安装所需依赖包

yarn add history @types/history react-router-dom @types/react-router-dom react-router-redux @types/react-router-redux redux-actions @types/redux-actions redux-thunk @types/redux-thunk redux --D

*注意:

(1).redux 已经包含TypeScript包

(2).redux-thunk:2.20目前会报语法错误,解决方法:

修改node_modules/redux-thunk/index.d.ts

import { Middleware, Dispatch, Action, AnyAction } from 'redux';export type ThunkAction<R, S, A extends Action = AnyAction, E = {}> = {
 (dispatch: Dispatch<A, S>, getState: () => S, extraArgument: E): R
}

declare module 'redux' { export interface Dispatch<A extends Action = AnyAction, S = {}> {
     <R, E>(thunk: ThunkAction<R, S, A, E>): R
 }
}

declare const thunk: Middleware & {
  withExtraArgument(extraArgument: any): Middleware;
};export default thunk;

3.开始编码
(1) 新建一个models.ts

// store中初始状态的接口声明export interface ITodoModel {
   id?: number;
   text: string;
   completed: boolean;
}

(2) 新建一个types.ts

// action 的唯一标识符  export const ADD_TODO = 'ADD_TODO';

(3) 新建一个anctions.ts

/**
*** 因为store中状态是只读的(可以使用store.getState()来获取整个store的 
状态)
 *** 要改变它里面的状态只能分发一个action去改变其属性  
 **/// createAction 让你可以轻松创建一个actionimport {createAction} from 'redux-actions';import {ITodoModel} from './models';import {ADD_TODO} from './types';const addTodo = createAction<ITodoModel, string>(
    ADD_TODO,
    (text: string) => ({text, completed: false})
);export {
    addTodo
}

(4) 新建一个reducers.ts

import {handleActions} from 'redux-actions';import {ADD_TODO} from './types';import {ITodoModel} from './models'// 初始的状态,就像react中组件内的初始状态,只不过这个是全局的。const initialState: ITodoModel = {    completed: true,    id: 1,    text: 'Use Redux',
};export const todoReducer = handleActions<ITodoModel>({
     [ADD_TODO]: (state: any, action: any) => {       console.log('reducer->state:', state);       console.log('reducer->action:', action);       return {completed: true, text: action.payload.text, id: 2};
   },
}, initialState);

(5) 开始组建store

  1. store->initState.ts

import {ITodoModel} from '../containers/home/modules/models';

export interface IRootState {
   todo: ITodoModel;
}
  1. store->reducer.ts

import {combineReducers} from 'redux';import {todoReducer} from '../containers/home/modules/reducers';// 把前面的reducers combine 起来const rootReducer = combineReducers({    todo: todoReducer as any
 }); export default rootReducer;
  1. store->reducer.ts

import {Store, createStore, applyMiddleware} from 'redux';import {routerMiddleware} from 'react-router-redux';import thunkMiddleware from 'redux-thunk';import rootReducer from './reducer';import {IRootState} from './initState';import {History} from 'history';export function configureStore(history: History, initialState?: IRootState): Store<IRootState> {// store 中间件,根据个人需求添加const middleware = applyMiddleware(
    thunkMiddleware,
    routerMiddleware(history)); return createStore(
      rootReducer as any,
      initialState as any,
      middleware
  ) as Store<IRootState>;
}

(6) 修改入口文件index.tsx

import * as React from 'react';import * as ReactDOM from 'react-dom';import {Provider} from 'react-redux';import registerServiceWorker from './registerServiceWorker';import Routers from './containers/Routers';import createHistory from 'history/createBrowserHistory'import {configureStore} from './store';const history = createHistory();const store = configureStore(history);

ReactDOM.render(   <Provider store={store}>
       <Routers/>
   </Provider>
 ,document.getElementById('root') as HTMLElement
);
registerServiceWorker();

(7) 如何使用?

import * as React from 'react';import {Dispatch} from 'redux';import {connect} from 'react-redux';import {addTodo} from './containers/home/modules/anctions';import {Button} from 'antd';import './App.less';

interface IAppProps {
    addTodo?: any;
    todos?: any;
}class App extends React.Component<IAppProps> {constructor(props: any) {    super(props);
}// 组件内分发action,改变store中的属性值public change = () => {    const myName = '我叫二白';    this.props.addTodo(myName)
};// 把store绑定在视图层上public render() {    console.log(this.props);    return (        <div className='App'>
            <div>{this.props.todos.todo.text}</div>

            <Button onClick={() => this.change()}>redux点击一下</Button>
        </div>
    );
  }
}// mapStateToProps(state, ownProps) 方法允许我们将store中的数据作为 // props绑定到组件中,只要store更新了就会调用mapStateToProps方法,// mapStateToProps返回的结果必须是object对象,该对象中的值将会更组件中;const mapStateToProps = (state: any) => ({todos: state
});// mapDispatchToProps(dispatch, [ownProps]) 第二个参数允许我们将action // 作为props绑定到组件中,// mapDispatchToProps希望你返回包含对应action的object对象; const mapDispatchToProps = (dispatch: Dispatch<any>) => {  return {      addTodo: (payload: string) => dispatch(addTodo(payload)),
  }
};export default connect(mapStateToProps, mapDispatchToProps)(App);



作者:黄二白
链接:https://www.jianshu.com/p/c5001d40ab25


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消