亚洲see少妇裸体pics,欧美日产欧美日产免费一区,亚洲综合av一区二区三区不卡,一区二区中文字幕无码成人片,一区二区三区四区高清无码

Redux使用

Redux使用

Redux狀態(tài)管理架構

1. Action類(lèi)型定義

// src/actions/types.js
export const USER_LOGIN = 'USER_LOGIN';
export const USER_LOGOUT = 'USER_LOGOUT';
export const SET_TOKEN = 'SET_TOKEN';
export const SET_MENUS = 'SET_MENUS';
export const SET_LOADING = 'SET_LOADING';
export const SET_ERROR = 'SET_ERROR';
export const CLEAR_ERROR = 'CLEAR_ERROR';

2. Action創(chuàng )建函數

// src/actions/userActions.js
import * as types from './types';

// 用戶(hù)登錄
export const userLogin = (userInfo) => ({
    type: types.USER_LOGIN,
    payload: userInfo
});

// 用戶(hù)登出
export const userLogout = () => ({
    type: types.USER_LOGOUT
});

// 設置token
export const setToken = (token) => ({
    type: types.SET_TOKEN,
    payload: token
});

// 設置菜單
export const setMenus = (menus) => ({
    type: types.SET_MENUS,
    payload: menus
});

// 異步登錄Action
export const loginUser = (username, password) => {
    return async (dispatch) => {
        dispatch(setLoading(true));
        
        try {
            const res = await post(allUrl.user.login, {}, {
                userId: username,
                password: md5(password)
            });
            
            if (res.msgKey) {
                dispatch(userLogin(res.result));
                dispatch(setToken(res.result.token));
                sessionStorage.setItem('token', res.result.token);
            } else {
                dispatch(setError(res.msgInfo));
            }
        } catch (error) {
            dispatch(setError('登錄失敗'));
        } finally {
            dispatch(setLoading(false));
        }
    };
};

3. Reducer實(shí)現

用戶(hù)Reducer

// src/reducers/userReducer.js
import * as types from '../actions/types';

const initialState = {
    token: sessionStorage.getItem('token') || '',
    userInfo: {},
    menus: [],
    account: {}
};

const userReducer = (state = initialState, action) => {
    switch (action.type) {
        case types.USER_LOGIN:
            return {
                ...state,
                userInfo: action.payload,
                account: action.payload.account || {}
            };
            
        case types.USER_LOGOUT:
            sessionStorage.removeItem('token');
            return {
                ...initialState,
                token: ''
            };
            
        case types.SET_TOKEN:
            return {
                ...state,
                token: action.payload
            };
            
        case types.SET_MENUS:
            return {
                ...state,
                menus: action.payload
            };
            
        default:
            return state;
    }
};

export default userReducer;

通用Reducer

// src/reducers/commonReducer.js
import * as types from '../actions/types';

const initialState = {
    loading: false,
    error: null,
    success: null
};

const commonReducer = (state = initialState, action) => {
    switch (action.type) {
        case types.SET_LOADING:
            return {
                ...state,
                loading: action.payload
            };
            
        case types.SET_ERROR:
            return {
                ...state,
                error: action.payload,
                success: null
            };
            
        case types.CLEAR_ERROR:
            return {
                ...state,
                error: null
            };
            
        case types.SET_SUCCESS:
            return {
                ...state,
                success: action.payload,
                error: null
            };
            
        default:
            return state;
    }
};

export default commonReducer;

組件連接Redux

1. 使用connect連接組件

// src/components/UserProfile.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { userLogout, setMenus } from '../actions/userActions';

class UserProfile extends Component {
    componentDidMount() {
        // 組件掛載時(shí)加載菜單
        this.loadMenus();
    }

    loadMenus = async () => {
        const { setMenus } = this.props;
        
        try {
            const res = await post(allUrl.user.getMenus, {});
            if (res.msgKey) {
                setMenus(res.result);
            }
        } catch (error) {
            console.error('加載菜單失敗:', error);
        }
    };

    handleLogout = () => {
        this.props.userLogout();
        this.props.history.push('/login');
    };

    render() {
        const { userInfo, menus, loading } = this.props;
        
        return (
            <div className="user-profile">
                <div>歡迎, {userInfo.userName}</div>
                <Button onClick={this.handleLogout}>退出登錄</Button>
                
                {loading && <Spin />}
                
                <Menu mode="horizontal" selectedKeys={[]}>
                    {menus.map(menu => (
                        <Menu.Item key={menu.zyDm}>
                            {menu.zyMc}
                        </Menu.Item>
                    ))}
                </Menu>
            </div>
        );
    }
}

// 映射state到props
const mapStateToProps = (state) => ({
    userInfo: state.user.userInfo,
    menus: state.user.menus,
    loading: state.common.loading
});

// 映射dispatch到props
const mapDispatchToProps = {
    userLogout,
    setMenus
};

export default connect(mapStateToProps, mapDispatchToProps)(UserProfile);

2. 使用Hooks連接組件

// 使用Hooks的函數組件
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { setLoading, clearError } from '../actions/commonActions';

const UserDashboard = () => {
    const userInfo = useSelector(state => state.user.userInfo);
    const loading = useSelector(state => state.common.loading);
    const error = useSelector(state => state.common.error);
    const dispatch = useDispatch();

    const handleRefresh = async () => {
        dispatch(setLoading(true));
        
        try {
            // 刷新數據邏輯
            await refreshUserData();
        } catch (error) {
            console.error('刷新失敗:', error);
        } finally {
            dispatch(setLoading(false));
        }
    };

    if (error) {
        return (
            <Alert 
                message="錯誤" 
                description={error}
                type="error"
                closable
                onClose={() => dispatch(clearError())}
            />
        );
    }

    return (
        <div className="user-dashboard">
            <Card title="用戶(hù)信息">
                <p>用戶(hù)名: {userInfo.userName}</p>
                <p>公司: {userInfo.companyName}</p>
                <Button onClick={handleRefresh} loading={loading}>
                    刷新數據
                </Button>
            </Card>
        </div>
    );
};

export default UserDashboard;

中間件使用

1. Promise中間件配置

// 配置promise中間件
import promiseMiddleware from 'redux-promise-middleware';

const store = createStore(
    rootReducer,
    applyMiddleware(promiseMiddleware)
);

// 使用promise中間件的Action
export const fetchUserData = () => ({
    type: 'FETCH_USER_DATA',
    payload: post(allUrl.user.getInfo, {})
});

// Reducer處理promise中間件生成的action
const userReducer = (state = initialState, action) => {
    switch (action.type) {
        case 'FETCH_USER_DATA_PENDING':
            return { ...state, loading: true };
            
        case 'FETCH_USER_DATA_FULFILLED':
            return { 
                ...state, 
                loading: false,
                userInfo: action.payload.result 
            };
            
        case 'FETCH_USER_DATA_REJECTED':
            return { 
                ...state, 
                loading: false,
                error: action.payload 
            };
            
        default:
            return state;
    }
};

2. 自定義中間件

// 日志中間件
const loggerMiddleware = store => next => action => {
    console.log('dispatching:', action);
    const result = next(action);
    console.log('next state:', store.getState());
    return result;
};

// 錯誤處理中間件
const errorHandlerMiddleware = store => next => action => {
    try {
        return next(action);
    } catch (error) {
        console.error('Action執行錯誤:', error);
        store.dispatch(setError(error.message));
        throw error;
    }
};

// 應用中間件
const store = createStore(
    rootReducer,
    applyMiddleware(loggerMiddleware, errorHandlerMiddleware, promiseMiddleware)
);

數據持久化

1. Redux Persist配置

// 持久化配置
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';

const persistConfig = {
    key: 'root',
    storage,
    whitelist: ['user'], // 只持久化用戶(hù)相關(guān)狀態(tài)
    blacklist: ['common'] // 不持久化通用狀態(tài)
};

const persistedReducer = persistReducer(persistConfig, rootReducer);

// 創(chuàng  )建持久化store
const store = createStore(persistedReducer);
const persistor = persistStore(store);

2. 自定義持久化轉換器

// 自定義序列化轉換器
import { createTransform } from 'redux-persist';

// 只持久化部分用戶(hù)信息
const userTransform = createTransform(
    // 存入時(shí)的轉換
    (inboundState, key) => {
        return {
            token: inboundState.token,
            userInfo: {
                userId: inboundState.userInfo.userId,
                userName: inboundState.userInfo.userName
            }
        };
    },
    // 取出時(shí)的轉換
    (outboundState, key) => {
        return outboundState;
    },
    { whitelist: ['user'] }
);

const persistConfig = {
    key: 'root',
    storage,
    transforms: [userTransform]
};

性能優(yōu)化

1. Reselect選擇器

// 創(chuàng  )建記憶化選擇器
import { createSelector } from 'reselect';

// 基礎選擇器
const getUser = state => state.user;
const getMenus = state => state.user.menus;

// 記憶化選擇器
export const getActiveMenus = createSelector(
    [getMenus],
    (menus) => menus.filter(menu => menu.status === 'active')
);

export const getUserPermissions = createSelector(
    [getUser],
    (user) => user.userInfo.permissions || []
);

// 在組件中使用
const mapStateToProps = (state) => ({
    activeMenus: getActiveMenus(state),
    permissions: getUserPermissions(state)
});

2. 避免不必要的重新渲染

// 使用React.memo優(yōu)化函數組件
const UserList = React.memo(({ users, onUserSelect }) => {
    return (
        <List
            dataSource={users}
            renderItem={user => (
                <List.Item onClick={() => onUserSelect(user)}>
                    {user.userName}
                </List.Item>
            )}
        />
    );
});

// 使用shouldComponentUpdate優(yōu)化類(lèi)組件
class UserTable extends Component {
    shouldComponentUpdate(nextProps, nextState) {
        // 只有當users數據變化時(shí)才重新渲染
        return nextProps.users !== this.props.users;
    }
    
    render() {
        // 渲染邏輯
    }
}

錯誤邊界和異常處理

1. Redux錯誤邊界

// 錯誤邊界組件
class ErrorBoundary extends Component {
    constructor(props) {
        super(props);
        this.state = { hasError: false };
    }
    
    static getDerivedStateFromError(error) {
        return { hasError: true };
    }
    
    componentDidCatch(error, errorInfo) {
        // 將錯誤發(fā)送到Redux store
        this.props.dispatch(setError(error.message));
        console.error('組件錯誤:', error, errorInfo);
    }
    
    render() {
        if (this.state.hasError) {
            return <ErrorFallback />;
        }
        
        return this.props.children;
    }
}

export default connect()(ErrorBoundary);

2. 異步操作錯誤處理

// 統一的錯誤處理函數
const handleAsyncError = (error, dispatch) => {
    if (error.response) {
        // 服務(wù)器返回錯誤
        dispatch(setError(error.response.data.message));
    } else if (error.request) {
        // 網(wǎng)絡(luò )錯誤
        dispatch(setError('網(wǎng)絡(luò )連接失敗'));
    } else {
        // 其他錯誤
        dispatch(setError(error.message));
    }
};

// 在A(yíng)ction中使用
export const fetchData = () => async (dispatch) => {
    try {
        const data = await api.fetchData();
        dispatch({ type: 'FETCH_SUCCESS', payload: data });
    } catch (error) {
        handleAsyncError(error, dispatch);
    }
};

這些Redux使用模式為應用提供了強大的狀態(tài)管理能力,包括數據流控制、異步操作處理、性能優(yōu)化和錯誤處理。

文章目錄

    亚洲see少妇裸体pics,欧美日产欧美日产免费一区,亚洲综合av一区二区三区不卡,一区二区中文字幕无码成人片,一区二区三区四区高清无码