初始化项目
npm init vite
package.json
{
"name": "react18-demo",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite --host --port 3000",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@ant-design/icons": "^4.8.0",
"antd": "^4.24.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^7.2.8",
"react-router-dom": "^6.3.0",
"redux": "^4.1.2",
"redux-thunk": "^2.4.2"
},
"devDependencies": {
"@types/node": "^18.11.9",
"@types/react": "^18.0.24",
"@types/react-dom": "^18.0.8",
"@vitejs/plugin-react": "^2.2.0",
"less": "^2.7.1",
"sass": "^1.56.1",
"typescript": "^4.6.4",
"vite": "^3.2.3",
"vite-plugin-style-import": "^1.4.1"
}
}
配置 @ 别名
vite.config.ts
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
import path from "path"
export default defineConfig({
plugins: [ react() ],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src")
}
}
})
tsconfig.json
{
"compilerOptions": {
...
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
}
}
类型定义
- 在 src 目录下,新建 xxx.d.ts 文件 (vite 会自动读取.d.ts 文件识别类型定义)
可新建多个类型定义,如
type.d.ts
、api.d.ts
、global.d.ts
等等 以 redux 使用到的类型为例子
type RootStateType = ReturnType<typeof import("@/store").getState>
interface Window {
__REDUX_DEVTOOLS_EXTENSION__: function;
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__: function
}
Redux 使用方式
新建目录及文件
-
src
目录下新建store
目录,在store
目录下新建index.ts
文件 -
store
目录下 新建user
目录,在user
目录下新建index.ts
、reducer.ts
两个文件 -
store
目录下 新建num
目录,在num
目录下新建index.ts
、reducer.ts
两个文件 -
两个目录下的
reducer.ts
文件内容如下:
import handle from "./index"
const reducer = (state = { ...handle.state }, action: { type: string, value: any }) => {
let newState = JSON.parse(JSON.stringify(state))
const actionList = Object.keys(handle.actions)
if (actionList.some(item => item === action.type)) {
handle.actions[action.type](newState, action.value)
}
return newState
}
export default reducer
user
和num
两个目录下的index.ts
文件内容如下:
// 存放方法, 写法使用箭头函数 xxx: () => {}
// 不可使用 xxx() {}
// 两个目录下的 actions 不用,自行调整即可,对应的是修改state中的值
const actions: any = {
// 改变 state.age
setAge: (newState: { age: number }, value: number) => {
newState.age = value
},
// 改变 state.role
setRole: (newState: { role: [] }, value: []) => {
newState.role = value
}
}
export default {
// state 存放数据
state: {
name: "Lucky",
role: [0, 1, 2, 3],
sex: 0,
age: 33
},
actions
}
store
目录下index.ts
文件内容如下:
import { legacy_createStore, combineReducers, compose, applyMiddleware } from "redux"
import reduxThunk from "redux-thunk"
import user from "./user/reducer"
import num from "./num/reducer"
// 使用 combineReducers 合并多个模块的数据
const reducers = combineReducers({
user,
num
})
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose
const store = legacy_createStore(reducers, composeEnhancers(applyMiddleware(reduxThunk)))
export default store
使用 Redux
main.tsx
引入并注册store
import React from "react"
import ReactDOM from "react-dom/client"
import { Provider } from "react-redux"
import store from "./store"
import { BrowserRouter } from "react-router-dom"
import App from "./App"
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<Provider store={ store }>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
)
- 页面中使用数据
import { useSelector, useDispatch } from "react-redux"
// 使用
const { num } = useSelector((state: RootStateType) => state.num)
const { role } = useSelector((state: RootStateType) => state.user)
// 调用 actions,改变 state 中的值
const dispatch = useDispatch()
const change = () => {
dispatch({ type: "setAge", value: 100 })
}