@Maa-Kut

Как увязать React router и Redux-редьюсеры?

Доброго всем дня.

Нужна помощь вот с таким моментом. Пилю приложение на React+Redux с роутенгом (SPA и все такое). В приложении есть форма, по заполнении которой пользователь жмет некую кнопку, форма проверяется, пользователя кидает на другую "страничку" (т.е. роут). Валидацию формы планировал изначально сделать в редьюсере: там и state весь виден, и вообще это как-то логично, т.к. именно редьюсер отвечает за обновление состояния приложения (в том числе на уровне "валидно/невалидно").

Проблема в том, что не знаю, как бы половчее по окончании проверки сделать тот самый переход на следующую страницу. Дергать в редьюсере push вроде бы неправильно (это больше к action creators относится). Можно в редьюсере выставлять в state какие-то флаги, увидев которые форма вместо отрисовки себя инициирует переход на другую страницу, но этот выглядит как-то костыльно.

Поделитесь, плз, опытом, кто как вообще подобные проблемы решает?
  • Вопрос задан
  • 589 просмотров
Пригласить эксперта
Ответы на вопрос 1
devellopah
@devellopah
просто мысли вслух

// types
const types = {
	UPDATE_FIELD: 'UPDATE_FIELD',
};
//types

// operations
const updateField = (value, error) => (
	{ type: types.UPDATE_FIELD, value, error }
);

// reducer
const initialState = { 
	values: {email: '', password: ''}, 
	errors: { email: '', password: '' } 
};

function someFormReducer(state = initialState, action) {
	switch(action.type) {
		case types.UPDATE_FIELD: {
			return { 
				values: { ...state.values, ...action.value }, 
				errors: { ...state.errors, ...action.error };
		}
	}
	
	return state;
}
// reducer

// так примерно выглядит global store
{
	...
	...
	form: {
		login: {
			values: {
				email: '',
				password: '',
			},
			errors: {
				email: '',
				password: ''
			}
		},
	}
}
// так примерно выглядит global store


import React from 'react';
import { validateEmail, validatePassword } from 'someValidateLibrary';
import { connect } from 'react-redux';
import { browserHistory } from 'react-router';
	
import { updateField } from 'path to operations file (action creators)' 

class SomeForm extends React.Component {
	
	handleValueChange = (e) => {
		const field = e.target.name;
		let error = '';
		
		if(field === 'email' && !validateEmail(field)) {
			error = "You email is so bad, seriously!";
		} 
		else if (!validationPassword(field) ) {
			error = "Your password is sucks!"
		}
		
		this.props.dispatch(
			updateField(
				{ field: e.target.value.trim() }, 
				{ field: error.trim() }
			)
		);
	} 

	proccessForm = () => {
		const { errors } = this.props;
		// если ошибок больше нет, то переход на другой роут
		if(!errors.email && !errors.password) {
			browserHistory.push('/home');
		} else {
			// your code here
		}
		
	}
	
	render() {
		const { values, errros } = this.props;
		
		return (
			// some ui
			<form onSubmit={this.proccessForm}>
				<p class="form-field">
					<input 
						type="email" 
						name="email" 
						onChange={this.handleValueChange} 
						value={values.email} 
					/>
					<span>{errors.email}</span>
				</p>
				<p class="form-field">
					<input 
						type="text" 
						name="password" 
						onChange={this.handleValueChange} 
						value={values.password} 
					/>
					<span>{errors.password}</span>
				</p>
				<button 
					type="submit" 
					disabled={!values.email && !values.password}>
						submit
				</button>
			</form>
		);
	}
}

const mapStateToProps = ({ form: { login } }) => (
  { values: login.values, errors: login.errors }
);
	

connect(mapDispatchToProps)(SomeForm);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы