react-typescript的一些简单使用,引入antd、redux,按需加载

react脚手架typescript版本整合redux、antd按需加载的简单使用(如有侵权,请联系我)

1.下载create-react-app

cnpm i create-react-app -g //全局下载react脚手架,mac用户加上sudo

2.创建react项目(注意:进入启动测试一下项目是否能正常运行)

create-react-app ts-react-study --typescript //--typescript创建脚手架默认引入typescript

3.引入antd,配置按需加载(antd官方有介绍,可以去官方api查看,这里就不用贴了,相信到这里的都是大佬,也可以继续看下去) antdAPI官网链接

cnpm i antd --save //antd就是typescript写的,不需要引入@types/antd这样的依赖

4.引入react-app-rewired、babel-plugin-import、customize-cra依赖配置按需加载

cnpm i react-app-rewired babel-plugin-import customize-cra --save

5.创建一个config-overrides.js文件在根目录下

config-overrides.js文件代码如下

const { override, fixBabelImports,addLessLoader } = require("customize-cra");

module.exports = override(
    // addDecoratorsLegacy(),//使用装饰器 //需要引入@babel/plugin-proposal-decorators依赖,next ts可以使用 react ts版本无法使用
    fixBabelImports("import", { libraryName: 'antd', style: true }),//style为true则表示使用未编译的less样式,这是可以定制主题色了
    addLessLoader({
        javascriptEnabled: true,
        modifyVars: { '@primary-color': 'red' }//配置主题色
    })
);

6.这时候重新启动会报错,这时候我们还需要less和less-loader,这样就不会报错了

cnpm i less less-loader --save

7.修改package.json文件(把scripts下面的start、test、build替换如下代码)

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject",
    "client": "serve build"
  }

重新启动项目 引入antd测试一下样式是否自动导入(修改index.tsx文件)

import React from 'react';
import ReactDOM from 'react-dom';
import {Button} from 'antd';

const Root: React.FC = () => (
    <Button>按钮</Button>
);
ReactDOM.render(<Root />, document.getElementById('root') as HTMLElement);

8.如需要使用scss的大佬,可以直接引入,react脚手架内部有对应的配置

cnpm i sass sass-loader node-sass -D

然后创建一个scss文件测试一下样式是否生效

9.引入react-router-dom路由

cnpm i react-router-dom @types/react-router-dom --save

10.引入redux、react-redux、react-thunk(重点使用)

cnpm i redux react-redux react-thunk @types/react-redux @types/react-thunk -D

11.制作一个简单的计数器案例

11.1创建store目录在src下面

11.2创建actions.ts文件

import { INCREMENT_COUNTER, DECREMENT_COUNTER, INCREMENT_ACTION_TYPE, DECREMENT_ACTION_TYPE } from './types';
import { Dispatch } from 'redux';

const incrementCount = (number: number): INCREMENT_ACTION_TYPE => ({ type: INCREMENT_COUNTER, number });
//异步action
export const asyncIncrementCount = (number: number) => (dispatch: Dispatch<INCREMENT_ACTION_TYPE>) => {
    setTimeout(() => dispatch(incrementCount(number)), 1000);
}
export const decrementCount = (number: number): DECREMENT_ACTION_TYPE => ({ type: DECREMENT_COUNTER, number });

11.3创建reducers.ts文件

import { ACTION_TYPE, INCREMENT_COUNTER, DECREMENT_COUNTER } from "./types";

interface CountState {
    count: number
}
export const initialState: CountState = {
    count: 0
}
export function countReducer(state = initialState, action: ACTION_TYPE):CountState {
    switch (action.type) {
        case INCREMENT_COUNTER:
            return { ...state, count: state.count + action.number };
        case DECREMENT_COUNTER:
            return { ...state, count: state.count - action.number };
        default:
            return state;
    }
}

11.4创建types.ts文件

export const INCREMENT_COUNTER = "INCREMENT_COUNTER";
export type INCREMENT_COUNTER = typeof INCREMENT_COUNTER;

export const DECREMENT_COUNTER = "DECREMENT_COUNTER";
export type DECREMENT_COUNTER = typeof DECREMENT_COUNTER;

// action类型
export interface INCREMENT_ACTION_TYPE{
    type:INCREMENT_COUNTER;
    number:number;
}
export interface DECREMENT_ACTION_TYPE{
    type:DECREMENT_COUNTER;
    number:number;
}
export type ACTION_TYPE = INCREMENT_ACTION_TYPE | DECREMENT_ACTION_TYPE;//reducer的action接收的类型

11.5创建index.ts文件

import { createStore, combineReducers, applyMiddleware } from "redux";
import thunk from 'redux-thunk';
import { countReducer, initialState } from "./reducers";
const reducers = combineReducers({
    countReducer
});
//引入组合后的
export type reducerType = ReturnType<typeof reducers>;//获取合并后的reducers类型
//第一个参数就是组合后的reducers 第二个参数就是默认值 第三个就是异步的thunk那些
export default createStore(reducers, {
    countReducer:initialState
}, applyMiddleware(thunk));

11.6创建hello.tsx在component目录下

import React, { Component } from 'react';
import { Button, Input } from 'antd';
interface State {
    name: string,
    value: string,
    [name: string]: number | string
}
interface Props {
    title: string;
    content?: string;
    handleMsg: Function;
}
export default class Hello extends Component<Props, State>{
    public constructor(props: Props) {
        super(props);
    }
    //只读属性只能读
    public readonly state = {
        name: "Hello",
        value: ""
    }
    private handleClick = () => {
        const { handleMsg } = this.props;
        const { value } = this.state;
        if (!value) return;
        this.setState({ name: value });
        handleMsg(value);
    }
    private handleChange = (e: React.FormEvent<HTMLInputElement>) => {
        // console.log(e.currentTarget.value);
        const { name, value } = e.currentTarget;
        this.setState({ [name]: value });
    }
    public render() {
        const { title } = this.props;
        const { name, value } = this.state;
        return (
            <>
                <h2>{title}</h2>
                <p>{name}</p>
                <p>value: {'  ' + value}</p>
                <Input onChange={this.handleChange} value={value} name="value" />{/* 需要设置name*/}
                <Button onClick={this.handleClick}>改变name</Button>
            </>
        );
    }
}

11.7创建pages/counter.tsx文件

import React, { Component } from 'react';
import { Button } from 'antd';
import { connect } from 'react-redux';
import { RouteComponentProps } from 'react-router-dom';
import { reducerType } from '../store';
import { asyncIncrementCount, decrementCount } from '../store/actions';

interface CounterProps {
    count: number;
    asyncIncrementCount: Function;
    decrementCount: Function;
}
const mapStateToProps = (state: reducerType) => ({ count: state.countReducer.count });
const mapDispatchToProps = { asyncIncrementCount, decrementCount };

//RouteComponentProps:路由库自带的api的类型定义
class Counter extends Component<RouteComponentProps & CounterProps, {}>{
    private increment = () => {
        const { asyncIncrementCount } = this.props;
        asyncIncrementCount(2);
    }
    private decrement = () => {
        const { decrementCount } = this.props;
        decrementCount(2);
    }
    public render() {
        const { count } = this.props;
        return (
            <div>
                <p>count:{count}</p>
                <Button onClick={this.increment}>按钮+2</Button>
                <Button onClick={this.decrement}>按钮-2</Button>
            </div>
        );
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Counter);

11.8修改App.tsx文件

import React, { Component } from 'react';
import { Switch,Route,Redirect,NavLink } from 'react-router-dom';
import Hello from './component/hello';
import Counter from './pages/counter';
interface IState {
  message: string
}

class App extends Component<{}, IState>{
  public readonly state = {
    message: ""
  }
  public handleMsg = (message: string) => {
    this.setState({ message });
  }
  public render() {
    const { message } = this.state;
    return (
      <>
        <h1>{message}</h1>
        <Hello title="Hello Typescript" handleMsg={this.handleMsg} />
        <NavLink to="/counter" activeClassName="active">计数</NavLink>
        <Switch>
          <Route path="/counter" component={Counter}/>
          <Redirect to="/counter"/>
        </Switch>
      </>
    );
  }
}

export default App;

11.9最后修改index.tsx文件

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import { ConfigProvider} from 'antd';

import store from './store';
import App from './App';
import zhCN from 'antd/es/locale/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';

moment.locale('en');
const Root: React.FC = () => (
    <Provider store={store}>
        <Router>
            {/* 新版的antd用ConfigProvider配合moment使用国际化定义 */}
            <ConfigProvider locale={zhCN}>
                <App />
            </ConfigProvider>
        </Router>
    </Provider>
);
ReactDOM.render(<Root />, document.getElementById('root') as HTMLElement);

最终重启项目即可 (有什么不足之处可以提出意见)

如果想看案例的大佬则直接点击这里前往github获取代码

原文地址:https://blog.csdn.net/weixin_43902189/article/details/99681548

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我最大的一个关于TypeScript的问题是,它将原型的所有方法(无论访问修饰符)编译.例classExample{publicgetString():string{return"HelloWorld";}privategetNumber():number{return123;}}众所周知,访问修饰符仅在编译时检
我对React很新,我正在尝试理解子组件之间相互通信的简洁方法.在一个简单的组件中,我知道我可以使用props将数据传递给子节点,并让子节点的回调将数据传递回父组件.在稍微复杂的情况下,当我在父组件中有多个子组件时,子组件之间的通信会有点混乱.我不确定我应该为同级别的儿童组
我有一个非常简单的表单,我将用户电子邮件存储在组件的状态,并使用onChange函数更新状态.有一个奇怪的事情发生在我的onChange函数用函数更新状态时,我在键入时在控制台中得到两个错误.但是,如果我使用对象更新状态,则不会出现错误.我相信用函数更新是推荐的方法,所以我很想知道为
我发现接口非常有用,但由于内存问题我需要开始优化我的应用程序,我意识到我并不真正了解它们在内部如何工作.说我有interfaceFoo{bar:number}我用这种类型实例化一些变量:letx:Foo={bar:2}Q1:这会创建一个新对象吗?现在,假设我想改变bar的值.我这样做有两种
我得到了一个json响应并将其存储在mongodb中,但是我不需要的字段也进入了数据库,无论如何要剥离不道德的字段?interfaceTest{name:string};consttemp:Test=JSON.parse('{"name":"someName","age":20}')asTest;console.log(temp);输出:{name:'someName
我试图使用loadsh从以下数组中获取唯一类别,[{"listingId":"p106a904a-b8c6-4d2d-a364-0d21e3505010","section":"section1","category":"VIPPASS","type":"paper","availableTi
我有以下测试用例:it("shouldpassthetest",asyncfunction(done){awaitasyncFunction();true.should.eq(true);done();});运行它断言:Error:Resolutionmethodisoverspecified.SpecifyacallbackorreturnaPromise;n
我正在一个有角度的2cli项目中工作,我必须创建一个插件的定义,因为它不存在它的类型.这个插件取决于已经自己输入的主库,它可以工作.无论如何,我有两个文件主要的一个图书馆类型文件AexportclassAextendsB{constructor(...);methodX():void;}我需要为我的
我有三元操作的问题:leta=undefined?"Defined!":"DefinitelyUndefined",b=abc?"Defined!":"DefinitelyUndefined",//ReferenceErrorc=(abc!==undefined)?"Defined!":"DefinitelyUndefin
下面的代码片段是30秒的代码网站.这是一个初学者的例子,令人尴尬地让我难过.为什么这样:constcurrentURL=()=>window.location.href;什么时候可以这样做?constcurrentURL=window.location.href;解决方法:第一个将currentURL设置为一个求值为window.location.href的
我是TypeScript和AngularJS的新手,我正在尝试从我的API转换日期,例如:"8/22/2015"…到ISO日期.将日期正确反序列化为Date类型的TypeScript属性.但是,当我尝试以下命令时(在typescript中,this.dateDisplay的类型为string)this.dateDisplay=formats.dateTimeValue.toISOString
我的名为myEmployees的数组中有5个名字,但是当我运行代码时,它只打印出其中的3个.我相信这种情况正在发生,因为脚本中的for循环覆盖了它在HTML文档中编写的前一行.我怎样才能解决这个问题?YearlyBulletinBoardAnnouncements!CongratulationstoTaylor,youhavebeenheref
我看到有一种方法可以在摩纳哥编辑器中设置scrolltop.如何滚动到特定行而不是特定像素?解决方法:如在文档中:https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.icodeeditor.html滚动到顶部,在px中:editor.setScrollPosition({scrollTop:0});滚动到特定
在从同一个类继承的一个数组中收集各种不同的对象时,如何在TypeScript中设置一个优等的类,以便TypeScript不显示错误?我正在尝试这样:interfaceIVehicle{modelName:string}interfaceICarextendsIVehicle{numberOfDoors:number,isDropTop:boolean}inte
什么是TypescriptTypeScript是一种由微软开发的自由和开源的编程语言,它是JavaScript的一个超集,扩展了JavaScript的语法。作者是安德斯大爷,Delphi、C#之父(你大爷永远是你大爷)。把弱类型语言改成了强类型语言,拥有了静态类型安全检查,IDE智能提示和追踪,代码重构简单、可读性
0.系列文章1.使用Typescript重构axios(一)——写在最前面2.使用Typescript重构axios(二)——项目起手,跑通流程3.使用Typescript重构axios(三)——实现基础功能:处理get请求url参数4.使用Typescript重构axios(四)——实现基础功能:处理post请求参数5.使用Typescript重构axios(五
1.1Typescript介绍1.TypeScript是由微软开发的一款开源的编程语言,像后端java、C#这样的面向对象语言可以让js开发大型企业项目。2.TypeScript是Javascript的超级,遵循最新的ES6、Es5规范(相当于包含了es6、es5的语法)。TypeScript扩展了JavaScript的语法。3.最新的Vu
0.系列文章1.使用Typescript重构axios(一)——写在最前面2.使用Typescript重构axios(二)——项目起手,跑通流程3.使用Typescript重构axios(三)——实现基础功能:处理get请求url参数4.使用Typescript重构axios(四)——实现基础功能:处理post请求参数5.使用Typescript重构axios(
webpack.config.jsconstpath=require('path');constCopyWebpackPlugin=require('copy-webpack-plugin');constExtractTextPlugin=require('extract-text-webpack-plugin');const{CleanWebpackPlugin}=require('clean-webpac
我在这篇ECMAScriptpage上读到“class”是JavaScript的一部分.在这个关于TypeScript的页面上,我看到’class’也可以在Typescript中找到.我的问题是,开发未来JavaScript应用程序的正确方法是利用(a)JavaScript中的面向对象功能以及EMACScript7.0中可用的功能或(b)使用TypeScript