如何使用 react-redux-forms 和自定义 reducer 避免奇怪的表单对象嵌套

How to avoid weird nesting of forms objects using react-redux-forms and custom reducer

我正在尝试使用 react-redux-form 来管理我的表单,但是在我设置其他 reducer 时遇到了如何将其注入商店的问题。

我的店铺创建如下

import { createStore, applyMiddleware, compose } from 'redux'

import { browserHistory }   from 'react-router'
import { routerMiddleware } from 'react-router-redux'

import { makeRootReducer }  from '../reducer'

const makeStore = (initialState = {}) => {
  const middleware = [
    routerMiddleware(browserHistory)
    // other middlewares
  ]

  const store = createStore(
    makeRootReducer(),
    initialState,
    compose(
      applyMiddleware(...middleware)
    )
  )
  store.asyncReducers = {}

  return store
}

module.exports = makeStore

我的根reducer如下

import { combineReducers } from 'redux'
import { routerReducer }   from 'react-router-redux'
import { combineForms }    from 'react-redux-form'

import { initialLoginState } from './components/forms/login'

const makeRootReducer = (asyncReducers) => {
  const customReducers = {
    // other of my own imported reducers
  }

  const forms = {
    login: initialLoginState
  }

  const allReducers = {
    ...customReducers,
    forms: combineForms(forms, 'forms'),
    routing: routerReducer,
    ...asyncReducers
  }

  return combineReducers(allReducers)
}

// mutate the store just this once.
const injectReducer = (store, { key, reducer }) => {
  store.asyncReducers[key] = reducer // eslint-disable-line no-param-reassign
  store.replaceReducer(makeRootReducer(store.asyncReducers))
}

module.exports = {
  makeRootReducer,
  injectReducer
}

我的表格是这样的

  <Form model='forms.login' onSubmit={login => console.debug(login)}>
    <label>Email</label>
    <Control.text model='.username' />
    <label>Password</label>
    <Control type='password' model='.password' />
    <button type="submit">Login</button>
  </Form>

当我启动我的应用程序并检查状态时,我看到处于以下状态的表单:

state:
  forms:
    login:
      username: ''
      password: ''
    forms:
      $form:
        focus: false
        # ... etc
      login:
        $form:
          focus: false
          # ... etc
        username: ''
        password: ''

表格的行为符合预期。

如果我更改 allreducers 删除第二个 'forms' 参数,它看起来像这样:

  const allReducers = {
    ...customReducers,
    forms: combineForms(forms),
    routing: routerReducer,
    ...asyncReducers
  }

我的状态看起来一样

state:
  forms:
    login:
      username: ''
      password: ''
    forms:
      $form:
        focus: false
        # ... etc
      login:
        $form:
          focus: false
          # ... etc
        username: ''
        password: ''

但表格本身不再有效。

我真正想要的是一个看起来像

state
state:
  forms:
    login:
      $form:
        focus: false
        # ... etc
      username: ''
      password: ''

没有所有奇怪的嵌套重复。

最终在我的表单组件中,我需要能够访问表单的 errors 对象,我宁愿不必深入研究 state.forms.forms.login.$form.errors 因为当我应该能够查看 state.forms.login.$form.errors.

我应该如何将 combinedForms 与其他减速器一起注入到我的 combinedReducer 中?

在您给出的示例中,state.forms.login 将包含模型值。 state.forms.forms.login 将包含有关 form/field 状态的 react-redux-form 特定信息。

这是 react-redux-form 的预期功能。您的困惑可能源于使用 'forms' 作为组合表单的模型名称。