javascript - 将 `store` 设置为 reducer 的 `state` 参数

标签 javascript reactjs redux state store

我是 Redux(还有 React)的新手,所以这可能是一个非常基本的问题,但我无法在 Internet 上找到直接的答案。

我的应用程序上有一个注册屏幕,我称之为 SignUp .它非常简单,只有三个输入(emailpasswordpasswordCheck)和一个按钮(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并开始使用 reducer 而不是 handlers。 一切都适用于 password ,但是passwordCheck是一个不同的故事。因为我需要知道 Store 的 password根据 passwordCheck 检查它我一直无法(到目前为止?)在 passwordCheckReducer 上完成它.相反,我删除了 passwordCheckMessage , passwordCheckStylepasswordsMatch来自 passwordCheckReducer ,在 SignUp 上计算此值.不过,在我看来,这是解决整个问题的一种非常错误和丑陋的方式。

所以,相反,我想要一个更优雅、更像 Redux 的解决方案。

如果我能得到 store待在 passwordCheckReducerstate我可以设置 passwordsMatch和 reducer 中的其他人同时保持纯净。不幸的是,我一直无法做到(到目前为止?)。 所以,我想知道我想做的事情是否可行,或者是否有其他更理想的方法来做。

OBS1:网上随便找找,Redux官方文档都是关于初始化状态的1 .我不认为preloadedState不过,这是解决我的问题的方法,因为它用于初始化 store ,而不是让它在我的 reducer 上可用。相反,我只需要有 store - 即使是空的 - 对 passwordCheckReducer 可见. OBS2:我知道我可以通过 store作为 action 的关键,但由于 reducer 模式包含一个 stateaction中定义传递这样的论点对我来说似乎是多余的.

这是我的商店:

// 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))
});

最佳答案

如果我没记错的话,当您将 reducer 传递给 combineReducers 时,该 reducer 将接收 redux 模块状态(因此,initialState 是什么,而不是整个应用程序的根状态对象)。您无权访问其他 reducer 的状态。

您有几个选择。

我认为为 passwordpasswordCheck 使用单独的 reducer 有点矫枉过正。我会为整个表单使用一个 reducer :

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
}

关于javascript - 将 `store` 设置为 reducer 的 `state` 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54680686/

相关文章:

javascript - 使用 Redux/React 移动数组中的项目

reactjs - Apollo 错误处理与 React Native

javascript - 使用 BEM 的 className 和 css 模块的正确参数列表语法

reactjs - TypeScript: 'string | undefined' 不可分配给类型 'string'

animation - Redux/Flux(使用 ReactJS)和动画

javascript - AJAX 成功时无法显示 JSON 结果

javascript - 创建一个重复循环,其间有定时间隔

javascript - 函数(a,b){ a = b; } 不会改变 javascript 中 a 的值

javascript - React Native 应用程序中 Redux thunk 的奇怪行为

reactjs - Redux 操作不调用 reducer