likes
comments
collection
share

React18+Vite+Ts+redux

作者站长头像
站长
· 阅读数 17

生成一个vite+react+ts的项目

执行命令

npm create vite

选择react

React18+Vite+Ts+redux

选择 ts

React18+Vite+Ts+redux

cd vite-project
//安装依赖
npm install
//启动项目
npm run dev

ts以及vite的一些配置

根目录下的tsconfig.json配置ts

{
  "compilerOptions": {
    "target": "ES2020",//指定 ECMAScript 目标版本,如 "ES3", "ES5", "ES2015", "ES2020", 或 "ESNEXT"。默认为 "ES3"。
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"], // 编译过程或运行时需要引入的库文件的列表
    "module": "ESNext",//指定模块代码生成的目标。常见选项有 "commonjs", "amd", "umd", "system", "es2015", "es2020", 或 "esnext"。默认为 "commonjs"。
    "skipLibCheck": true,// 跳过所有声明文件的类型检查

    /* Bundler mode */
    "moduleResolution": "bundler",// 指定模块的解析策略
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true, // 允许使用 .json 扩展名导入的模块
    "isolatedModules": true,
    "noEmit": true,// 不输出(意思是不编译代码,只执行类型检查
    "jsx": "react-jsx",// 在 .tsx 文件里支持 JSX:"react" 或 "react-native"

    /* Linting */
    "strict": true,//启用所有严格类型检查
    "noUnusedLocals": true,// 生成相应的.d.ts文件
    "noUnusedParameters": true,// 报告未使用参数的错误
    "noFallthroughCasesInSwitch": true,
    "baseUrl": "./", /* 设置项目的基本路径*/
    "paths": {
        "@utils/*": ["src/utils/*"],
        "@service/*": ["src/service/*"],
        "@components/*": ["src/components/*"],
        "@views/*": ["src/views/*"],
        "@route/*": ["src/route/*"],
        "@store/*": ["src/store/*"],
        "@types/*": ["src/types/*"],
        "@styles/*": ["src/styles/*"],
    }, /* 重新映射包的相对路径 */
  },
  "include": ["src"],// *** TypeScript文件应该进行类型检查 ***
  "references": [{ "path": "./tsconfig.node.json" }]
}

根目录下的vite.config.ts => Vite 的配置信息

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { resolve } from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],//插件
  resolve: {//解析
    alias: {//别名  这些别名在项目的代码中可以用作简化导入路径的方式
      '@': resolve(__dirname, 'src'),
      '@utils': resolve(__dirname, 'src/utils'),
      '@service': resolve(__dirname, 'src/service'),
      "@assets": resolve(__dirname, "src/assets"),
      "@components": resolve(__dirname, "src/components"),
      "@views": resolve(__dirname, "src/views"),
      "@layout": resolve(__dirname, "src/layout"),
      "@config": resolve(__dirname, "src/config"),
      "@store": resolve(__dirname, "src/store"),
      "@route": resolve(__dirname, "src/route"),
    }
  },
  server: {
    port: 3000,//端口号
    proxy: {//代理
      "/api": {
        target: "https://",
        changeOrigin: true,// 如果需要跨域,则设置为 true  
        cookieDomainRewrite: "",// 如果需要重写 cookie 域名,请填写相应的值 
        secure: false,// 如果您的代理服务器��持 HTTPS,可以设置为 true 
      },
    },
  }
})

redux

安装redux

Redux是一个JavaScript状态容器,为应用程序(特别是React应用程序)提供集中的状态管理。 对于小型或简单的应用程序,使用React的本地状态和props可能已经足够了。然而,随着应用程序的规模和复杂性的增加,Redux可以提供更多的好处和优势。

什么场景下适用redux?

  1. 全局状态管理:当你的应用程序中有一些状态需要在多个组件之间共享时,Redux是一个很好的选择。Redux提供了一个中心化的store来保存这些状态,并允许你通过actions和reducers来更新它们。
  2. 复杂的异步操作:Redux的middleware(如redux-thunk、redux-saga或redux-observable)可以帮助你处理复杂的异步操作。
  3. 大型或复杂的应用程序:对于大型或复杂的单页面应用程序,通过将所有状态保存在一个中心化的store中,你可以更容易地理解和调试应用程序的状态。
  4. 跨组件通信:Redux允许你在不直接相关的组件之间传递数据。通过使用Redux的actionsreducers,你可以将数据从一个组件发送到另一个组件,而无需将它们直接链接在一起或使用复杂的父子组件传递。

核心

  • reducer 接收当前的应用状态和一个动作(action),然后返回一个新的状态。Reducers是纯函数,对于相同的输入总是返回相同的输出。
  • action Actions是事件,它们传递来自应用程序(如用户接口、内部事件如API调用和表单提交)的数据给store。Actions是简单的具有一个type属性(通常是常量)的JavaScript对象,这个对象描述了action的类型以及传递给store的负载信息。
  • storeStore是Redux应用程序中单一的状态容器。它保存了整个应用程序的状态,并且这个状态不能直接被改变。当一些数据变化时,一个新的对象就会被创建(使用actions和reducers)。
npm i react-router-dom redux react-redux redux-thunk

创建store

在根目录下的store文件夹创建index.ts文件

// src/store/index.js
import { createStore, applyMiddleware } from "redux";
// 用于支持异步action
import thunk from "redux-thunk";//这个中间件允许你在 action 创建函数中返回函数,以实现异步逻辑。
import reducers from "./reducer";

export default createStore(reducers, applyMiddleware(thunk))

创建reducer

在store文件夹下创建reducer文件夹

//src/store/reducer/nameReducer.ts
import { SET_AGE, SET_NAME } from "../constants";
 
const nameState = {
  name: "岚岚同学",
  age: 18,
};
 
export const nameReducer = (state = nameState, action : any) => {
  const {type,data,payload} = action
  switch (type) {
    case SET_AGE:
      return {
        ...state,
        age: state.age + payload,
      };
    case SET_NAME:
      return {
        ...state,
        name: data,
      };
    default:
      return state;
  }
}

合并reducer

//src/store/reducer/index.ts
import { combineReducers } from "redux";
import { nameReducer } from "./nameReducer";

export default combineReducers({
  nameReducer,
});

创建action

在store下创建actions文件夹

//src/store/actions/nameAction.ts
import { SET_AGE, SET_NAME } from '../constants'
 
export const setAge = function (age) {
  return {
    type: SET_AGE,
    payload:age
  };
};
export const setName = function (name:string) {
  return {
    type: SET_NAME,
    data: name,
  };
};

/* export const getList = () => {
  return async (dispatch) => {
      const { data } = await get_list();
      dispatch({
          type: "GET_LIST",
          payload: data[0]
      })
  }
} */

constants.ts文件,用于定义action中的type,唯一性

//src/store/constants.ts
export const SET_AGE = "set_age";
export const SET_NAME = "set_name";

使用 Provider 包裹你的应用

Provider 组件由 Redux 的 React 绑定库 react-redux 提供。在 React 应用的最顶层,你需要使用 Provider 组件来包裹你的应用。这将使 Redux store 在整个组件树中可用。

//main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import { Provider } from "react-redux";
import store from './store'

ReactDOM.createRoot(document.getElementById('root')!).render(
  // <React.StrictMode> 
  <Provider store={store}>
    <App />
  </Provider>
  // </React.StrictMode>,
)

在组件中使用store

在组件中通过useSelector来获取store中的状态,通过useDispatch来获取action中的方法

//src/views/About.tsx
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { setAge, setName } from '../store/actions/nameAction'
import { stateType } from "@types/about.type.ts";
// import '../scss/about.scss'

function About() {
  const dispatch = useDispatch()
  const name = useSelector((state:stateType) => state.nameReducer.name)
  const age = useSelector((state:stateType) => state.nameReducer.age)
  const [val, changeVal] = useState('')
  const changeValue = (e) => {
    const text = e.target.value
    changeVal(text)
  }
  const changeName = () => {
    dispatch(setName(val))
  }
  const changeAge = () => {
    dispatch(setAge(1))
  }
  return (
    <div className="about">
      <div>
        <p>名字是:{name}</p>
        <input type="text" onChange={changeValue} />
        <button onClick={changeName}>修改姓名</button>
        <p>年龄是:{age}</p>
        <button onClick={changeAge}>+1</button>
      </div>
    </div>
  );
}

export default <About/>;

react-router

react-router 用于处理客户端路由

安装react-router

npm i react-router-dom

设置路由表

// src/route/index.ts
import LayoutCom from '../components/Layout'
import Home from '../views/Home'
import About from '../views/About'

const routes = [
  {
    path: '/',
    element: LayoutCom,
    children: [
      {
        path: '/home',
        element: Home,
        name: '首页',
      },
      {
        path: '/about',
        element: About,
        name: '关于',
      },
    ]
  }
]
export default routes

配置路由

在APP中正确配置路由

import { useRoutes } from 'react-router-dom';//用于接收一个路由配置对象,并返回与当前URL路径对应的React组件。
import routes from '@route/index'; //引入路由
import { ConfigProvider } from 'antd';//全局化配置
import zhCN from 'antd/es/locale/zh_CN'; //国际化配置中文
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import 'antd/dist/reset.css';

dayjs.locale('zh-cn');

const App = () => <ConfigProvider locale={zhCN}>{useRoutes(routes)}</ConfigProvider>
export default App;

使用BrowserRouter将路由集成到应用中

// main.tsx
import { StyleProvider, legacyLogicalPropertiesTransformer } from '@ant-design/cssinjs'
// import ReactDOM from 'react-dom'; // react18不支持这样引入ReactDOM
import { createRoot } from 'react-dom/client'; 
import { BrowserRouter } from 'react-router-dom'; // 利用了 HTML5 History API 来实现路由切换。BrowserRouter 创建的 URL 看起来就像常规的 URL,没有额外的字符或哈希(#)
import { Provider } from "react-redux";//通过 React 的 context API 将 Redux store 传递给整个组件树
import store from './store' // 引入store
import App from './App.tsx'
import './index.css'

const root = createRoot(document.getElementById('root')!);  
root.render(
  <Provider store={store}>
    <BrowserRouter>
      <StyleProvider hashPriority="high" transformers={[legacyLogicalPropertiesTransformer]}>
        <App />
      </StyleProvider>
    </BrowserRouter>

  </Provider>
);

配置完成仓库以及路由以后就可以正常访问页面,使用redux了。

这时候访问 http://127.0.0.1:3000/home 就可以看到下方的页面了

React18+Vite+Ts+redux

React18+Vite+Ts+redux

转载自:https://juejin.cn/post/7379252155339489290
评论
请登录