详细的讲一下React中的Redux

给大家详细讲一下React中的Redux,最近收到不少同学想让我说一说Redux,要是有不明白的地方,很欢迎大家私信来一起交流!!

1. Redux 核心概念

1. Store:存储状态的容器

2.Action:描述发生了什么的普通对象

3.Reducer:定义状态如何更新的纯函数

4Dispatch:发送 action 的方法

5.Subscribe:订阅 store 变化的方法

2. 基础设置

// 1. 安装依赖
npm install redux react-redux @reduxjs/toolkit

// 2. 创建 store 目录结构
src/
  store/
    index.js        // store 配置
    reducers/       // reducer 文件夹
    actions/        // action 文件夹
    types/          // action 类型常量

3. 创建 Store

// store/index.js
import { configureStore } from '@reduxjs/toolkit'
import rootReducer from './reducers'

const store = configureStore({
    reducer: rootReducer,
    middleware: (getDefaultMiddleware) => 
        getDefaultMiddleware().concat(logger),
    devTools: process.env.NODE_ENV !== 'production'
})

export default store

4. 定义 Action Types

// store/types/userTypes.js
export const USER_TYPES = {
    LOGIN_REQUEST: 'user/loginRequest',
    LOGIN_SUCCESS: 'user/loginSuccess',
    LOGIN_FAILURE: 'user/loginFailure',
    LOGOUT: 'user/logout'
}

// store/types/todoTypes.js
export const TODO_TYPES = {
    ADD_TODO: 'todo/add',
    REMOVE_TODO: 'todo/remove',
    TOGGLE_TODO: 'todo/toggle'
}

5. 创建 Action Creators

// store/actions/userActions.js
import { USER_TYPES } from '../types/userTypes'

export const userActions = {
    loginRequest: (credentials) => ({
        type: USER_TYPES.LOGIN_REQUEST,
        payload: credentials
    }),
    
    loginSuccess: (user) => ({
        type: USER_TYPES.LOGIN_SUCCESS,
        payload: user
    }),
    
    loginFailure: (error) => ({
        type: USER_TYPES.LOGIN_FAILURE,
        payload: error
    }),
    
    logout: () => ({
        type: USER_TYPES.LOGOUT
    })
}

// 异步 Action Creator
export const login = (credentials) => {
    return async (dispatch) => {
        dispatch(userActions.loginRequest(credentials))
        
        try {
            const response = await api.login(credentials)
            dispatch(userActions.loginSuccess(response.data))
        } catch (error) {
            dispatch(userActions.loginFailure(error.message))
        }
    }
}

6. 创建 Reducers

// store/reducers/userReducer.js
import { USER_TYPES } from '../types/userTypes'

const initialState = {
    user: null,
    loading: false,
    error: null
}

export const userReducer = (state = initialState, action) => {
    switch (action.type) {
        case USER_TYPES.LOGIN_REQUEST:
            return {
                ...state,
                loading: true,
                error: null
            }
            
        case USER_TYPES.LOGIN_SUCCESS:
            return {
                ...state,
                loading: false,
                user: action.payload
            }
            
        case USER_TYPES.LOGIN_FAILURE:
            return {
                ...state,
                loading: false,
                error: action.payload
            }
            
        case USER_TYPES.LOGOUT:
            return initialState
            
        default:
            return state
    }
}

7. 合并 Reducers

// store/reducers/index.js
import { combineReducers } from 'redux'
import { userReducer } from './userReducer'
import { todoReducer } from './todoReducer'

const rootReducer = combineReducers({
    user: userReducer,
    todos: todoReducer
})

export default rootReducer

8. 在 React 中使用

// index.js
import { Provider } from 'react-redux'
import store from './store'

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

// 组件中使用
import { useSelector, useDispatch } from 'react-redux'
import { userActions } from '../store/actions/userActions'

const UserComponent = () => {
    const dispatch = useDispatch()
    const { user, loading, error } = useSelector(state => state.user)
    
    const handleLogin = (credentials) => {
        dispatch(userActions.login(credentials))
    }
    
    const handleLogout = () => {
        dispatch(userActions.logout())
    }
    
    return (
        <div>
            {loading && <LoadingSpinner />}
            {error && <ErrorMessage error={error} />}
            {user ? (
                <UserProfile user={user} onLogout={handleLogout} />
            ) : (
                <LoginForm onSubmit={handleLogin} />
            )}
        </div>
    )
}

9. Redux Toolkit 使用(推荐)

// store/slices/userSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'

// 创建异步 action
export const loginAsync = createAsyncThunk(
    'user/login',
    async (credentials, { rejectWithValue }) => {
        try {
            const response = await api.login(credentials)
            return response.data
        } catch (error) {
            return rejectWithValue(error.message)
        }
    }
)

const userSlice = createSlice({
    name: 'user',
    initialState: {
        user: null,
        loading: false,
        error: null
    },
    reducers: {
        logout: (state) => {
            state.user = null
            state.error = null
        }
    },
    extraReducers: (builder) => {
        builder
            .addCase(loginAsync.pending, (state) => {
                state.loading = true
                state.error = null
            })
            .addCase(loginAsync.fulfilled, (state, action) => {
                state.loading = false
                state.user = action.payload
            })
            .addCase(loginAsync.rejected, (state, action) => {
                state.loading = false
                state.error = action.payload
            })
    }
})

export const { logout } = userSlice.actions
export default userSlice.reducer

10. 中间件使用

// store/middleware/loggerMiddleware.js
export const loggerMiddleware = (store) => (next) => (action) => {
    console.log('dispatching', action)
    const result = next(action)
    console.log('next state', store.getState())
    return result
}

// store/index.js
import { configureStore } from '@reduxjs/toolkit'
import { loggerMiddleware } from './middleware/loggerMiddleware'

const store = configureStore({
    reducer: rootReducer,
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware().concat(loggerMiddleware)
})

11. 最佳实践

1.使用 Redux Toolkit

  • 简化配置
  • 内置 immer 处理不可变更新
  • 自动配置 Redux DevTools
  • 包含常用中间件  

2.组织结构

  • 按功能模块划分
  • 使用 ducks 模式或 feature 文件夹

3. 性能优化

  • 使用 reselect 做选择器
  • 避免不必要的渲染
  • 合理拆分 state 

4 . 异步处理

  • 使用 createAsyncThunk
  • 处理加载状态和错误状态
  • 合理使用缓存

这就是 Redux 的主要使用方法和最佳实践。记住:

  • 保持 reducer 纯函数
  • 不要直接修改 state
  • 合理组织 action 和 reducer
  • 使用 Redux Toolkit 简化开发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值