State Management

Managing context, state and hooks

Context API

We are using context for login methods - Auth0, JWT, Firebase.

src/contexts/configContext.jsx
....
// project import
import defaultConfig from 'config';
import useLocalStorage from 'hooks/useLocalStorage';
....

// ==============================|| CONFIG CONTEXT & PROVIDER ||============================== //

const ConfigContext = createContext(initialState);

function ConfigProvider({ children }) {

....
    const onChangeMenuOrientation = (menuOrientation) => {
        setConfig({
            ...config,
            menuOrientation
        });
    };

    const onChangeMiniDrawer = (miniDrawer) => {
        setConfig({
            ...config,
            miniDrawer
        });
    };

    const onChangeMode = (mode) => {
        setConfig({
            ...config,
            mode
        });
    };
....

 return (
        <ConfigContext.Provider
            value={{
                ...config,
                onChangeMenuOrientation,
                onChangeMiniDrawer,
                onChangeMode,
                onChangePresetColor,
                onChangeLocale,
                onChangeDirection,
                onChangeContainer,
                onChangeFontFamily,
                onChangeBorderRadius,
                onChangeOutlinedField,
                onReset
            }}
        >
            {children}
        </ConfigContext.Provider>
    );
}

ConfigProvider.propTypes = {
    children: PropTypes.node
};

export { ConfigProvider, ConfigContext };

State

export const initialState = {
    isOpen: 'dashboard', //for active default menu
    navType: config.theme,
    locale: config.i18n,
    rtlLayout: false, // rtlLayout: config.rtlLayout,
    opened: true
};

Designing Actions

We designed the state structure based on the app's requirements.

Based on that list of things that can happen, we created list of actions that our application will use:

export const LOGIN = 'LOGIN';
export const LOGOUT = 'LOGOUT';
export const REGISTER = 'REGISTER';
export const FIREBASE_STATE_CHANGED = 'FIREBASE_STATE_CHANGED';

Writing Reducers

Creating the Root Reducer - A Redux app really only has one reducer function: the "root reducer" function

src/store/slice/contact.js
...
// project imports
import axios from 'utils/axios';
import { dispatch } from '../index';
...

...
const slice = createSlice({
    name: 'contact',
    initialState,
    reducers: {
        // HAS ERROR
        hasError(state, action) {
            state.error = action.payload;
        },

        // GET CONTACTS
        getContactsSuccess(state, action) {
            state.contacts = action.payload;
        },

        // MODIFY CONTACT
        modifyContactSuccess(state, action) {
            state.contacts = action.payload;
        }
    }
});
...

export function getContacts() {
    return async () => {
        try {
            const response = await axios.get('/api/contact/list');
            dispatch(slice.actions.getContactsSuccess(response.data.contacts));
        } catch (error) {
            dispatch(slice.actions.hasError(error));
        }
    };
}

export function modifyContact(contact) {
    return async () => {
        try {
            const response = await axios.post('/api/contact/modify', contact);
            dispatch(slice.actions.modifyContactSuccess(response.data));
        } catch (error) {
            dispatch(slice.actions.hasError(error));
        }
    };
}

Last updated