Установить `store` в качестве параметра` state` редуктора - PullRequest
0 голосов
/ 14 февраля 2019

Я новичок в Redux (и React также), так что это, вероятно, очень простой вопрос, но я не смог найти прямой ответ на него через Интернет.

Есть регистрацияэкран в моем приложении, которое я называю SignUp.Это довольно просто и имеет всего три входа (email, password и passwordCheck) и одну кнопку (signup).Дело в том, что я хочу сделать свою жизнь пользователя как можно более простой, чтобы при изменении passwordCheck я сравнивал ее с password.Если они совпадают, signup включается, а если нет, signup отключается и пользователю показывается сообщение.Когда я использовал только React, все было довольно просто - я просто сделал this.state:

this.state: {
    // ... stuff
    password: "",
    passwordIsValid: false, //test password against a predicate function
    passwordMessage: "", //if the password is not valid there is a message
    passwordStyle: "", //if password is wrong i put some classes here
    passwordCheck: "",
    passwordCheckMessage: "", //the 'passwords do not match' message goes here
    passwordCheckStyle: "",
    passwordsMatch: false
}

И затем я обработал состояние приложения внутри SignUp.Теперь я также использую Redux, поэтому я убил this.state, переместил все в store и начал использовать редукторы вместо обработчиков.Все работает для password, но passwordCheck - это отдельная история.Поскольку мне нужно знать password в Магазине, чтобы сравнить его с passwordCheck, я не смог (пока?) Сделать это на passwordCheckReducer.Вместо этого я удалил passwordCheckMessage, passwordCheckStyle и passwordsMatch из passwordCheckReducer, рассчитав эти значения на SignUp.Хотя мне кажется, что это очень неправильный и уродливый способ все уладить.

Так что вместо этого я бы хотел более элегантное и Redux-подобное решение.

Если бы я могполучить store для включения passwordCheckReducer state Я мог бы установить passwordsMatch и другие в редукторе, сохраняя его в чистоте.К сожалению, я не смог этого сделать (пока?).Итак, я хотел бы знать, возможно ли то, что я хочу сделать, или есть другие, более желательные, способы сделать это.

OBS1: Где бы я ни смотрел в Интернете, я нашел официальную документацию Redux попредмет начального состояния 1 .Я не думаю, что preloadedState - это способ решить мою проблему, так как он используется для инициализации store, а не для того, чтобы сделать его доступным для моих редукторов.Вместо этого мне просто нужно, чтобы store - даже когда он был пуст - был виден passwordCheckReducer.OBS2: я знаю, что мог бы передать store в качестве ключа action, но, поскольку шаблон редуктора включает аргумент state, мне кажется избыточным определять проход, такой как action.

Здесьмой магазин:

// store.js
import { applyMiddleware, createStore } from 'redux';
import { createLogger } from 'redux-logger';
import thunkMiddleare from 'redux-thunk';
import { Reducers } from '../reducers/reducers';

const logger = createLogger();
const middleware = applyMiddleware(thunkMiddleare, logger);

export const Store = createStore(Reducers, middleware);

Я использую combineReducers:

// reducers.js
import { combineReducers } from 'redux';
import { emailReducer } from './emailReducer';
import { passwordReducer } from './passwordReducer';
import { passwordCheckReducer } from './passwordCheckReducer';

export const Reducers = combineReducers({
    emailChange: emailReducer,
    passwordChange: passwordReducer,
    passwordCheckChange: passwordCheckReducer
}); 

А вот passwordCheckReducer:

// passwordCheckReducer.js
import { CHANGE_PASSWORDCHECK } from '../actions/actionTypes';

const initialState = {
    passwordCheck: ""
};

export const passwordCheckReducer = (state=initialState, action) => {
    const { payload, type } = action;

    switch(type) {
        case CHANGE_PASSWORDCHECK:
            const passwordCheck = payload;
            return {
                ...state,
                passwordCheck
            };
        default: 
            return state;
    }
};

Последнее, этореализация mapDispatchToProps:

// SignUp.js
const mapDispatchToProps = dispatch => ({
    handleEmailChange: e => dispatch(updateEmail(e.target.value)),
    handlePasswordChange: e => dispatch(updatePassword(e.target.value)),
    handlePasswordCheckChange: e => dispatch(updatePasswordCheck(e.target.value))
});

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Если вы комбинируете редукторы, существует только один объект хранилища, в котором хранится все состояние каждого редуктора.

Таким образом, вы можете получить доступ к нескольким редукторам из одного компонента, например так:

const mapStateToProps = state => ({
  password: state.passwordChange.password,
  passwordCheck: state.passwordCheckChange.passwordCheck,
  passwordsMatch: state.passwordCheckChange.passwordsMatch
})
export default connect(mapStateToProps, mapDispatchToProps)(SignUp)

Каждый раз, когда вы обновляете passwordCheck или password, реквизиты вашего компонента будут обновляться.

Таким образом, лучшим решением на самом деле является обработка паролей. Сопоставление - это пользовательская поддержка, полученная из состояния двух отдельных редукторов.Что-то вроде:

const mapStateToProps = state => {
  const passwordsMatch = state.passwordChange.password === state.passwordCheckChange.passwordCheck
  return {
    password: state.passwordChange.password, 
    passwordCheck: state.passwordCheckChange.passwordCheck,
    passwordsMatch: passwordsMatch
  }
}
0 голосов
/ 14 февраля 2019

Если я правильно помню, когда вы передаете ваш редуктор в combReducers, тот редуктор получит состояние модуля редуктора (то есть, каким было initialState, а не объект корневого состояния всего приложения).У вас нет доступа к состоянию от других редукторов.

У вас есть несколько вариантов.

Я думаю, что иметь отдельные редукторы для password и passwordCheck несколько излишне.Я бы использовал один редуктор для всей формы:

const initialState = {
    password: '',
    passwordCheck: '',
    // ....
}

export const signupReducer = (state=initialState, action) => {
    const { payload, type } = action;

    switch(type) {
        case CHANGE_PASSWORD:
            return { ...state, password: action.password}
        case CHANGE_PASSWORDCHECK:
            const passwordCheck = payload;
            if (state.password != state.passwordCheck) 
                return { ...state, passwordCheck, error: "..."}; // or something like this

            return {
                ...state,
                passwordCheck
            };
        default: 
            return state;
    }
};

Если вы хотите разделить вещи, вы всегда можете определить редукторы и вызывать их из родительского редуктора, передавая все состояние родительского редуктора.Что-то вроде:

import passwordReducer from './passwordReducer'
import passwordCheckReducer form './passwordCheckReducer'

export const signupReducer(state = initialState, action) => {
    state = passwordReducer(state, action)
    state = passwordCheckReducer(state, action)
    return state
}
...