Forms With Redux
// constants.js
export const PARTICIPANT_REGISTER_FORM_SET_VALUE = 'PARTICIPANT_REGISTER_FORM_SET_VALUE';
export const PARTICIPANT_REGISTER_FORM_SUBMIT = 'PARTICIPANT_REGISTER_FORM_SUBMIT';
export const PARTICIPANT_REGISTER_FORM_SUBMIT_SUCCESS = 'PARTICIPANT_REGISTER_FORM_SUBMIT_SUCCESS';
export const PARTICIPANT_REGISTER_FORM_SUBMIT_FAILED = 'PARTICIPANT_REGISTER_FORM_SUBMIT_FAILED';
// reducer.js
import {
PARTICIPANT_REGISTER_FORM_SET_VALUE,
PARTICIPANT_REGISTER_FORM_SUBMIT,
PARTICIPANT_REGISTER_FORM_SUBMIT_SUCCESS,
PARTICIPANT_REGISTER_FORM_SUBMIT_FAILED
} from './constants';
const initialState = {
form: {
name: '',
surname: '',
numberOfPets: null,
extraSocket: false,
ownRack: false,
}
// Добавили новые поля в хранилище
registrationRequest: false,
registrationFailed: false,
}
export const participantRegistrationReducer = (state = initialState, action) => {
switch(action.type) {
case PARTICIPANT_REGISTER_FORM_SET_VALUE: {
return {
form: {
...state.form,
[action.field]: action.value
}
}
}
case PARTICIPANT_REGISTER_FORM_SUBMIT: {
return {
...state,
registrationRequest: true,
registrationFailed: false
}
}
case PARTICIPANT_REGISTER_FORM_SUBMIT_SUCCESS: {
return {
...state,
form: {
// При успешной регистрацией сбрасываем форму до исходного состояния
...initialState.form
}
registrationRequest: false
}
}
case PARTICIPANT_REGISTER_FORM_SUBMIT_FAILED: {
return {
...state,
registrationRequest: false,
registrationFailed: true
}
}
default: {
return state;
}
}
}
// actions.js
import {
PARTICIPANT_REGISTER_FORM_SET_VALUE,
PARTICIPANT_REGISTER_FORM_SUBMIT,
PARTICIPANT_REGISTER_FORM_SUBMIT_SUCCESS,
PARTICIPANT_REGISTER_FORM_SUBMIT_FAILED
} from './constants';
export const setParticipantFormValue = (field, value) => ({
type: PARTICIPANT_REGISTER_FORM_SET_VALUE,
field,
value
});
export const register = () => (dispatch, getState) => {
dispatch({
type: PARTICIPANT_REGISTER_FORM_SUBMIT
});
fetch('/api/register', {
method: 'POST',
// В тело запроса помещаем значения из хранилища
body: JSON.stringify(...getState().participantRegistration.form)
}).then(res=>{
return res.json();
}).then(data => {
dispatch({
type: PARTICIPANT_REGISTER_FORM_SUBMIT_SUCCESS,
data
});
}).catch(err => {
dispatch({
type: PARTICIPANT_REGISTER_FORM_SUBMIT_FAILED,
});
})
}
import React from 'react';
import { useSelector, useReducer } from 'react-redux';
import { setParticipantFormValue, register } from './services/register/actions';
export const Registration = () => {
const {
name,
surname,
numberOfPets,
extraSocket,
ownRack
} = useSelector(state => state.participantRegistration.form);
// Используем статус выполнения запроса для блокировки кнопки регистрации
const { registrationRequest } = useSelector(state => state.participantRegistration);
const dispatch = useDispatch();
const onFormChange = (e) => {
if (e.target.name === 'extraSocket' || e.target.name === 'ownRack') {
dispatch(setParticipantFormValue(e.target.name, e.target.checked))
} else {
dispatch(setParticipantFormValue(e.target.name, e.target.value))
}
}
const onFormSubmit = (e) => {
// Предотвращаем дефолтное поведение формы при её отправке
e.preventDefault();
// Вызываем наш thunk-экшен
dispatch(register())
}
return (
<form onSubmit={onFormSubmit}>
<label htmlFor="name">Имя</label>
<input type="text" onChange={onFormChange} value={name} name="name" id="name" />
<label htmlFor="surname">Фамилия</label>
<input type="text" onChange={onFormChange} value={surname} name="surname" id="surname" />
<label htmlFor="numberOfPets">Количество питомцев</label>
<input type="number" min="1" onChange={onFormChange} value={numberOfPets} name="numberOfPets" id="numberOfPets"/>
<label htmlFor="extraSocket">Требуется дополнительная розетка</label>
<input type="checkbox" onChange={onFormChange} value={extraSocket} name="extraSocket" id="extraSocket"/>
<label htmlFor="ownRack">Собственный стеллаж</label>
<input type="checkbox" onChange={onFormChange} value={ownRack} name="ownRack" id="ownRack"/>
<button type="submit" disabled={registrationRequest}>Зарегистрироваться</button>
</form>
)
}