Используется библиотека redux
.
store
доступен отовсюду через import store form @src/store
.Всё состояние приложения декомпозируется на модули. В модуле определяются экшены, начальное состояние и редьюсер по установке состояния.
├──/store — модули состояния на redux
├──/articles
| ├── state.js
| ├── actions.js
| └── reducer.js
├──/session
| └──...
├──index.js — объект хранилища
└──reducers.js — реэкспорт редьюсеров из всех модулей состояний
Типы экшенов и начальное состояние описывается в отдельном файле {module}/state.js
.
Экшены — функции для выполнения различной логики и последующей смены состояния.
dispatch()
.store.dispatch({type, payload})
или store.getState()
{module}/actions.js
в виде методов объекта.Редьюсеры описываются в файле {module}/reducer.js
merge-change
для слияния нового состояния со старым.@src/store/reducers.js
Экшены формы входа src\store\form-login\actions.js
import store from '@src/store';
import * as api from '@src/api';
import initState, { types } from './state.js';
export default {
/**
* Изменение полей формы
* @param data
*/
change: data => {
store.dispatch({type: types.SET, payload: { data }});
},
/**
* Отправка формы в АПИ
* @param data
* @returns {Promise<*>}
*/
submit: async data => {
store.dispatch({ type: types.SET, payload: { wait: true, errors: null } });
try {
const response = await api.users.login(data);
//...
// сброс данных в форме
store.dispatch({ type: types.SET, payload: initState });
return result;
} catch (e) {
//..
}
},
};
Тип экшенов и начальное состояние src\store\form-login\state.js
export const types = {
SET: Symbol('SET'),
};
export default {
data: {
login: '',
password: '',
},
wait: false,
errors: null,
};
Редьюсер src\store\form-login\reducer.js
import reducer from '@src/utils/reducer';
import mc from 'merge-change';
import initState, { types } from './state.js';
export default reducer(initState, {
[types.SET]: (state, action) => {
return mc.update(state, action.payload);
},
});
Пример вызова экшенов в форме авторизации /src/app/login/index.js
import formLogin from '@src/store/form-login/actions';
function Login(props) {
//...
const callbacks = {
onChangeForm: useCallback(async data => {
// Экшен по установке данных из формы в общий стейт
await formLogin.change(data);
}, []),
onSubmitForm: useCallback(async data => {
// Отправка данных формы
await formLogin.submit(data);
//..
}, []),
};
// ...