react 初体验

https://zh-hans.react.dev/ 官方中文文档

https://segmentfault.com/a/1190000012921279 学习

1.react安装

利用工具来构建脚手架

复制代码
npm create vite@latest react项目名称 -- --template react

创建的时候比较慢 耐心等

创建完成后

复制代码
npm install
npm run dev    看好node版本  推荐21

2.添加 env

复制代码
VITE_TITLE='项目开发环境'
VITE_APP_ENV = 'devlopment'

  "scripts": {
    "dev": "vite --mode dev -d proxy",
    "test": "vite --mode test -d proxy",
    "prod": "vite --mode prod -d proxy",
    "build:test": "vite build --mode test",
    "build:prod": "vite build --mode prod",
    "lint": "eslint .",
    "preview": "vite preview"
  },

const env = import.meta.env;

<div className='title'>{env.VITE_TITLE}</div>

3.配置路由

https://blog.csdn.net/debbyDeng/article/details/84555817

复制代码
npm install  react-router-dom

import { createBrowserRouter } from 'react-router-dom'
import React from 'react'
import MainLayout from '../layouts/MainLayout.jsx' //用来存放公共模块

// React.lazy 表示懒加载页面组件
const Login = React.lazy(() => import('../pages/login/login.jsx'))
const Home = React.lazy(() => import('../pages/home/index.jsx'))
const router = createBrowserRouter([
    {
        path: '/login',
        Component: Login
    },
    {
        path: '/',
        Component: MainLayout,
        children: [{ index: true, Component: Home }]
    }
])
export default router

4.本地储存

复制代码
npm install redux-persist

本地储存持久化

复制代码
import { configureStore } from '@reduxjs/toolkit';
import countReducer from './modules/countStore';

// 👇 redux-persist 相关导入
import { persistStore, persistReducer } from 'redux-persist';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import storage from 'redux-persist/lib/storage'; // 使用 localStorage
// import { sessionStorage } from 'redux-persist/lib/storage' // 也可以使用 sessionStorage
// import AsyncStorage from '@react-native-async-storage/async-storage' // 移动端用 AsyncStorage

// 👇 配置持久化选项
const persistConfig = {
    key: 'root',           // 存储的 key
    storage,               // 存储引擎(localStorage)
    whitelist: ['count'],   // 只持久化的 reducer 名称(可选)  优先级高于 blacklist
        // blacklist: []       // 不想持久化的 reducer 名称 
    version: 1, // 版本号,当 reducer 数据结构变化时(比如新增了一个key 把object放到了这个key下面),需要更新版本号
    debug: process.env.NODE_ENV === 'development', // 开启调试模式,会在控制台打印哪些数据被保存/被恢复/有错误
    throttle: 2000, // 2秒保存一次  (默认是1000ms)
    migrate: (state, version) => { // 版本迁移函数 有点小复杂 后面再深究
       // 根据旧 state 和版本号,返回新 state
        return state;
    },
    stateReconciler: autoMergeLevel2, // 配置 state 合并策略 
    // 比如现在存了obj: { user: { name: '苗' }, count: 5 } 现在name是两层 如果现在user要变成obj: { user: { name: '苗', age: 24, }, count: 5, email: '123123' } 
    // 那么autoMergeLevel2会自动合并成obj: { user: { name: '苗', age: 24, }, count: 5, email: '123123' }
    keyPrefix: 'myapp_', // 自定义前缀,避免与其他应用冲突 存储时变成:keyPrefix的值 + persist: + key的值
};

// 👇 包装 reducer
const persistedReducer = persistReducer(persistConfig, countReducer);

// 👇 创建 store
export const store = configureStore({
  reducer: {
    count: persistedReducer
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false, // redux-persist 会报错,需关闭
    }),
});

// 👇 创建 persistor
export const persistor = persistStore(store);

// 💡 原来的 store 还是 export default
export default store;

单个 store 持久化

复制代码
// store/modules/countStore.ts
import { createSlice } from '@reduxjs/toolkit';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';

// 1. 配置持久化
const persistConfig = {
  key: 'count',        // localStorage 中的 key 是:myapp_persist:count
  storage,             // 使用 localStorage
  version: 1,
  keyPrefix: 'myapp_',  // 前缀
};

// 2. 创建 slice
const countStore = createSlice({
  name: 'count',
  initialState: {
    count: 0
  },
  reducers: {
    increment(state) {
      state.count++;
    },
    decrement(state) {
      state.count--;
    },
    changeCount(state, action) {
      state.count = action.payload;
    },
  }
});

// 3. 包装成持久化 reducer  关键一步!
const persistedReducer = persistReducer(persistConfig, countStore.reducer);

// 4. 导出 actions 和 持久化后的 reducer
export const selectCount = (state) => state.count.count;
export const { increment, decrement, changeCount } = countStore.actions;

//  最关键的一行:导出持久化后的 reducer
export default persistedReducer;

// store/modules/countStore.ts
import { createSlice } from '@reduxjs/toolkit';
import { persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';

// 1. 配置持久化
const persistConfig = {
    key: 'trigger',        // localStorage 中的 key 是:myapp_persist:count
    storage,             // 使用 localStorage
    version: 1,
    keyPrefix: 'myapp_',  // 前缀
};

// 2. 创建 slice
const triggerStore = createSlice({
    name: 'trigger',
    initialState: {
        trigger: 'sun',//触发主题 日月
        menuShow: true,//侧边栏
    },
    reducers: {
        changeTrigger(state, action) {
            state.trigger = action.payload;
        },
        changeMenuShow(state, action) {
            state.menuShow = action.payload;
        },
    },
    extraReducers: (builder) => {
        builder.addCase('persist/REHYDRATE', (state, action) => {
            // 1. 恢复 Redux 状态
            if (action.payload?.trigger) {
                state.trigger = action.payload.trigger;
            } else {
                // 如果没有持久化数据,用系统偏好
                const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
                state.trigger = prefersDark ? 'moon' : 'sun';
            }

            // 2.  立刻同步 DOM,避免闪烁
            if (state.trigger === 'moon') {
                document.documentElement.classList.add('dark');
            } else {
                document.documentElement.classList.remove('dark');
            }

            // 3. 添加初始化标记(可选)
            document.documentElement.classList.add('theme-initialized');
        });
    }
});

// 3. 包装成持久化 reducer 关键一步!
const persistedReducer = persistReducer(persistConfig, triggerStore.reducer);

// 4. 导出 actions 和 持久化后的 reducer
export const selectTrigger = (state) => state.trigger.trigger;
export const selectMenuShow = (state) => state.trigger.menuShow;

export const { changeTrigger, changeMenuShow } = triggerStore.actions;

// ✅ 最关键的一行:导出持久化后的 reducer
export default persistedReducer;

✅ 总结:persistConfig 配置一览

|-------------------|----------|--------------|-----------------------------|
| 配置项 | 是否必填 | 作用 | 建议值 |
| key | ✅ 必填 | 存储的 key 名 | 'root' |
| storage | ✅ 必填 | 存储引擎 | import storage from '...' |
| whitelist | ❌ 可选 | 只存这些 reducer | ['count'] |
| blacklist | ❌ 可选 | 不存这些 reducer | ['loading'] |
| version | ❌ 可选 | 版本号 | 1 |
| debug | ❌ 可选 | 是否打印日志 | 开发时 true |
| throttle | ❌ 可选 | 防抖时间 | 2000 |
| migrate | ❌ 可选 | 数据迁移 | 复杂时使用 |
| stateReconciler | ❌ 可选 | 合并策略 | autoMergeLevel2 |
| keyPrefix | ❌ 可选 | key 前缀 | 可选 |

相关推荐
三掌柜6663 小时前
2025三掌柜赠书活动第三十五期 AI辅助React Web应用开发实践:基于React 19和GitHub Copilot
前端·人工智能·react.js
JacksonGao3 小时前
Next.js的App router和Pages router的区别你知道多少?
react.js·next.js
鹏多多4 小时前
React自定义Hooks设计指南:从封装到复用
前端·javascript·react.js
小菜全11 小时前
《React vs Vue:选择适合你的前端框架》
vue.js·react.js·前端框架
duansamve17 小时前
React 18项目中使用环境变量(适用于不同环境下的配置常量)
react.js
小刘鸭地下城20 小时前
告别服务端渲染卡顿!useSyncExternalStore 优化水合作用全解析
react.js
Winson℡21 小时前
如何理解 React Native 中的 useEffect
javascript·react native·react.js
乖女子@@@1 天前
React-props的children属性
前端·javascript·react.js
八月十八1 天前
React常用Hooks及使用示例大全
前端·javascript·react.js