比较全面的typescript + react 开发教程
前言
本教程不用react-script
这种工具,用的webpack
+ eslint(可选)
+ prettier(可选)
+ babel
,使用编辑器用的vscode。
以下会涉及到ts语法和redux
、react-router-dom
的一些技巧,也是入门时学习到的。
准备工作
depend
# babel
yarn add @babel/core @babel/preset-reac @babel/preset-typescript @babel/preset-env -D
# webpack
yarn add webpack webpack-cli webpack-dev-server html-webpack-plugin babel-loader css-loader fork-ts-checker-webpack-plugin -D
# react-hot-reload
yarn add @pmmmwh/react-refresh-webpack-plugin react-refresh type-fest -D
# react 相关
yarn add react react-dom react-redux react-router-dom redux-thunk
# 以上的这些react相关全部装个type,例子
# yarn add @types/react @types/react-dom ... -D
# eslint 可选
yarn add babel-eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-prettier eslint-plugin-prettier eslint-plugin-react-hooks -D
envfile
tsconfig.json
这里我的工程文件都放在./src
里
{"compilerOptions": {"baseUrl": ".","paths": {"@root/*": ["src/*"]},"outDir": "./dist/","sourceMap": true,"noImplicitAny": true,"lib": ["es6","es7","dom"],"target": "es5","jsx": "react","allowJs": true,"experimentalDecorators": true,"allowSyntheticDefaultImports": true},"include": ["./src/**/*"]
}
.babelrc
{"presets": ["@babel/preset-env","@babel/preset-typescript","@babel/preset-react"]
}
.eslintrc.js
module.exports = {root: true,env: {commonjs: true,es6: true,browser: true,node: true,},parser: '@typescript-eslint/parser',plugins: ['@typescript-eslint', 'prettier'],extends: ['eslint:recommended','plugin:@typescript-eslint/recommended','plugin:react-hooks/recommended','plugin:prettier/recommended','prettier',],parserOptions: {ecmaFeatures: {jsx: true,},},ignorePatterns: ['dist', 'lib'],rules: {'@typescript-eslint/no-var-requires': 0,'@typescript-eslint/no-unused-vars': 0,'prefer-const': 0,'@typescript-eslint/no-explicit-any': 0,'react-hooks/exhaustive-deps': 0,},
}
.prettierrc
{"semi": false,"singleQuote": true
}
webpack.dev.js
const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')module.exports = {entry: './src/index.tsx',output: {filename: 'app.js',path: path.join(__dirname, './dist'),publicPath: '/',},context: path.resolve(__dirname, './src'),devtool: 'cheap-module-source-map',devServer: {hot: true,// enable HMR on the servercompress: true,contentBase: path.resolve(__dirname, './src'),// match the output pathpublicPath: URL,historyApiFallback: true,},mode: 'development',module: {rules: [{test: /\.[tj]sx?$/,exclude: /node_modules/,use: ['babel-loader'],},{test: /\.css$/i,use: ['style-loader',{loader: 'css-loader',options: {modules: {mode: 'global',localIdentName: '[name]__[local]--[hash:base64:5]',},importLoaders: 2,},},],},],},resolve: {alias: {'@root': path.resolve(__dirname, './src'),},extensions: ['.ts', '.tsx', '.js', '.json'],},plugins: [// 用来检测开发中ts语法错误问题new ForkTsCheckerWebpackPlugin({typescript: {configFile: path.resolve(__dirname, './tsconfig.json'),},}),new ReactRefreshWebpackPlugin(),new HTMLWebpackPlugin({template: './src/app.html',filename: 'index.html',}),],
}
基本开发
index.tsx
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import App from '@root/App'ReactDOM.render(<App />, document.getElementById('app'))
App.tsx
import * as React from 'react'
import { Provider } from 'react-redux'
import { BrowserRouter, Route, Switch } from 'react-router-dom'
// 这里redux下面会给写法
import store from './reducers'const App: React.FC = function App(props) {return (<Provider store={store}><BrowserRouter><Switch><Route path="/a1"><div>page a1</div></Route><Route path="/"><div>home</div></Route></Switch></BrowserRouter></Provider>)
}
export default App
redux相关
这里以多个模块组合为例
/reducers/folder.ts
// 定义state
export type FolderDstate = {folders: {name: string}[]isLoading: booleanloaded: boolean
}
let dstate: FolderDstate = {folder: [],isLoading: false,loaded: false,
}// 集合所有action
export type FolderAction =| FolderLoad| FolderUpdatetype FolderLoad = {type: 'folder/load'folders: {name: string}[]
}
type FolderUpdate = {type: 'folder/update'isLoading?: booleanloaded?: boolean
}let folder = (state = dstate, action: FolderAction): FolderDstate => {switch (action.type) {case 'folder/update': {return {...state,isLoading: action.isLoading ?? state.isLoading,loaded: action.loaded ?? state.loaded,}}case 'folder/load': {return {...state,folders: [...action.folders],}}
}
export default folder
这里用的switch
是因为vscode会有case
提示
并且每块case
中的变量都是相对独立于上面定义的type的
/reducers/index.ts
import { combineReducers, createStore, applyMiddleware, compose } from 'redux'
import thunkMiddleware from 'redux-thunk'
import folder, { FolderAction, FolderDstate } from './folder'let rootReducer = combineReducers({folder,
})let store = (function configureStore() {// 这里是添加插件使chrome的redux插件能检测并使用
// 这里window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__会被ts爆出错误,以下会给解决方案const middlewares = [thunkMiddleware]const middlewaresEnhancer = applyMiddleware(...middlewares)const composeEnhancers =window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || composeconst store = createStore(rootReducer,composeEnhancers(middlewaresEnhancer))return store
})()export default store
// 这里放进去所有的模块默认state type
export type StateBase = {folder: FolderDstate//other: otherDstate
}
// 这里放进去所有的action集合,用|连接
export type RootActions = FolderAction /*| otherAction */
redux-connect用法
import * as React from 'react'
import { connect, ConnectedProps } from 'react-redux'
// --- 这里的Dispatch最好用一个ts文件集中管理,这里方便就放一起了 ---
import { RootActions, StateBase } from '@root/reducers'
import { Dispatch } from 'redux'export const loadFolder = (isForce = false) => (dispatch: Dispatch<RootActions>,getState: () => StateBase
): Promise<void> => {const state = getState()if (state.folder.isLoading || (!isForce && state.user.loaded)) returndispatch({ type: 'folder/load', folders: [] })dispatch({ type: 'folder/update', loaded:true })
}
// -------------// 定义传入参数,ConnectedProps是把connect里的所有方法和变量都打包一起了
type Props = ConnectedProps<typeof connector> & {//自定义参数
}const Comp1: React.FC<Props> = (props) => {React.useEffect(()=>{props.loadFolder()},[])return <div>{`${props.loaded}`}</div>
}const mapStateToProps = (state: StateBase) => {return {loaded: state.folder.loaded,}
}const mapDispatchToProps = {loadFolder
}let connector = connect(mapStateToProps, mapDispatchToProps)export default connector(Comp1)
loadFolder
里的dispatch
方法提示,都会根据type提示需要的参数
单独带提示的dispatch useDp.ts
import { RootActions } from '@root/reducers'
import { useDispatch } from 'react-redux'export const useDp = (): React.Dispatch<RootActions> =>useDispatch<React.Dispatch<RootActions>>()
效果
关于ts的一些东西
全局变量
在./src
下随便建个什么的global.d.ts
,放一些ts没法检测的全局变量
interface Window {__REDUX_DEVTOOLS_EXTENSION_COMPOSE__: (...any: any) => any
}
将type变成全部可选的新type
export type DeepPartial<T> = {[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K]
}
// 这里FolderDstate的所有属性就变成全选了
type n = DeepPartial<FolderDstate>
动态key
如果用了eslint使用object类型他会报错,这样就是动态key了
type dykey = {[key:string]:any
}
end
npx webpack serve --config webpack.dev.js
就ok了
比较全面的typescript + react 开发教程相关推荐
- 最全面的Unity游戏开发指南视频教程 第2卷
最全面的Unity游戏开发指南视频教程 第2卷 流派:电子学习| MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小 ...
- react开发教程(十)redux结合react
描述 Redux 和 React 之间没有关系.Redux 可以搭配 React.Angular 甚至纯 JS.但是 Redux 还是比较适合和 React 搭配的,因为 React 允许你以 sta ...
- 最全面的Android Studio使用教程【申明:来源于网络】
最全面的Android Studio使用教程[申明:来源于网络] http://www.admin10000.com/document/5496.html 转载于:https://www.cnblog ...
- react开发教程(九)redux基础
Readux基础 什么是redux? 简单点回答就是,一个管理数据的全局对象,但是它有单一状态树的概念,所谓的单一状态树,就是指"所有的 state都以一个对象树的形式储存在一个单一的 st ...
- 史上最全面的python学生管理系统教程(二)
目录 序言 sqlite使用教程 python sqlite使用教程 数据库构造 学生信息表结构: 教师信息表结构: 课程成绩表结构: 教师添加课程: 学生表连接课程成绩表: 数据库语句了解 sqli ...
- 一篇很全面的freemarker 前端web教程
FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成: 1,文本:直接输出的部分 2,注释:<#-- ... -->格式部分,不 ...
- python中的类装饰器应用场景_这是我见过最全面的Python装饰器教程了!
装饰器(Decorators)是 Python 的一个重要部分.简单地说:他们是修改其他函数的功能的函数.他们有助于让我们的代码更简短,也更Pythonic(Python范儿).在程序开发中经常使用到 ...
- 最全面的WordPress建站教程,零基础30分钟学会建站
宝塔面板添加WordPress站点 一.建站准备条件 条件1:阿里云服务器一台.原则上有台服务器就好了,不过我一般喜欢用大品牌,稳定和安全. 条件2: 阿里云域名一个.在哪家买的服务器,就用哪家的域名 ...
- 最强最全面的Hive SQL开发指南,超四万字全面解析!
本文整体分为两部分,第一部分是简写,如果能看懂会用,就直接从此部分查,方便快捷,如果不是很理解此SQl的用法,则查看第二部分,是详细说明,当然第二部分语句也会更全一些! 第一部分: hive模糊搜索表 ...
最新文章
- 计算机本科学位有用吗_我应该回到学校获得计算机科学学位吗?
- Web前端开发人员和设计师必读文章推荐【系列七】
- 委托与事件代码详解与(Object sender,EventArgs e)详解
- 《基于张量网络的机器学习入门》学习笔记6
- Jerry的反省:程序员不要轻易说出“这个功能技术上无法实现“
- java dll 乱码_java调用c++ dll出现中文乱码 | 学步园
- [html] 如何设置打印尺寸?
- python import如何使用_python之import引用
- 「深入浅出」主流前端框架更新批处理方式
- 草稿 图片盒子定时器模式窗口
- 【clickhouse】ClickHouse官方中文文档 阅读笔记
- 又来?软件测试之接口自动化面试题汇总
- 小程序用php的优势,小程序的特点及优势?
- JS面向对象的程序设计(二)
- SQLServer之创建Transact-SQL DDL触发器
- 此语言无法安装在此计算机上win10,如何解决Win10换成无法安装英文语言包的问题...
- steam服务器连接不稳定WIN10,小编操作win10系统steam连接不稳的解决步骤
- 可视化图布局算法浅析
- 浏览器屏蔽百度推广广告
- 【机器学习】07. 决策树模型DecisionTreeClassifier(代码注释,思路推导)