【问题标题】:Loading initial values from state in redux form以 redux 形式从 state 加载初始值
【发布时间】:2018-12-30 23:23:14
【问题描述】:

我正在尝试在 Redux 表单中加载初始值(我从对服务器的异步调用中获得),但没有任何反应。 服务器调用工作正常(我可以看到我的 redux 状态正在更新),但表单不显示值。

我阅读了有关堆栈溢出的所有问题,并应用了所有解决方案,但没有任何效果:

我通过 connect 函数传递 initialValues(使用来自异步调用的初始值进行更新),并将 enableReinitialize: true 添加到 reduxForm()

我的代码如下。我没有展示动作或减速器,因为我相信它们工作正常(我将它们用于没有问题的其他视图)。

import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom'
import { reduxForm, Field } from 'redux-form';

import { BASEURL } from '../config'

import { updateBenefit, fetchBenefit } from '../actions';


class SubsidyTiming extends Component {

  componentWillMount() {
    this.props.fetchBenefit(this.props.match.params.benefit)
  }

  renderField(field) {
    return (
      <div className="form-group">
        <label>{field.label}</label>
        <input
          className="form-control"
          type={field.type}
          {...field.input}/>
      </div>
    )
  }

  renderSelect(field) {
    return (
      <div className="form-group">
        <label>{field.label}</label>
        <select
          className="form-control"
          {...field.input}>
            {field.children}
        </select>
      </div>
    )
  }

  onSubmit = (values) => {
  this.props.updateBenefit(values, this.props.match.params.benefit, (subsidy_name) => {
    this.props.history.push(`${BASEURL}/benefits`)
  }); }


  render() {
    if (!this.props.initialValues) {
      return (<h1>{I18n.t("loading")}</h1>)
    }

    return (
      <div>
        <form onSubmit={this.props.handleSubmit(this.onSubmit)}>
          <Field
            label={I18n.t("benefits.new.start.subsidy")}
            name="opening_date"
            type="date"
            component={this.renderField}
          />
          <Field
            label={I18n.t("benefits.new.end.subsidy")}
            name="closing_date"
            type="date"
            component={this.renderField}
          />
          <Field
            label={I18n.t("benefits.new.is_renewable.subsidy")}
            name="is_renewable"
            type="checkbox"
            component={this.renderField}
          />
          <Field
            label={I18n.t("benefits.new.frequency.subsidy")}
            name="frequency"
            type="select"
            component={this.renderSelect}
          >
            <option></option>
            <option value="weekly">{I18n.t("frequency.weekly")}</option>
            <option value="monthly">{I18n.t("frequency.monthly")}</option>
            <option value="quarterly">{I18n.t("frequency.quarterly")}</option>
            <option value="semiannually">{I18n.t("frequency.semiannually")}</option>
            <option value="annually">{I18n.t("frequency.annually")}</option>
          </Field>
          <button
            className="btn btn-primary"
            type="submit"
            disabled={this.props.pristine || this.props.submitting}>
            Sauver et continuer
          </button>
        </form>

      </div>
    )
  }

}

function mapStateToProps(state, ownProps) {
  return {
    initialValues: state.benefit
  }
}

export default reduxForm({ form: 'updateSubsidyForm', enableReinitialize: true })(
  connect(mapStateToProps, { updateBenefit, fetchBenefit })(SubsidyTiming)
);

感谢您的帮助!


编辑

这是我的 action.js 文件:

import { APIENDPOINT } from '../config'

export const FETCH_BENEFIT = 'FETCH_BENEFIT'


const csrfToken = document.querySelector('meta[name="csrf-token"]').attributes.content.value;


export function fetchBenefit(benefit) {
  const url = `${APIENDPOINT}/${benefit}`
  const promise = fetch(url, { credentials: 'same-origin' }).then(r => r.json())

  return {
    type: FETCH_BENEFIT,
    payload: promise
  }
}

export function updateBenefit(body, name, callback) {
  const promise = fetch(`${APIENDPOINT}/${name}`, {
    method: 'PUT',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      'X-CSRF-Token': csrfToken
    },
    credentials: 'same-origin',
    body: JSON.stringify(body)
  }).then(r => r.json())
    .then(r => callback(r.name))

  return {
    type: BENEFIT_UPDATED,
    payload: promise
  }
}

还有我的 benefit_reducer.js 文件

import { FETCH_BENEFIT } from '../actions';

export default function(state = null, action) {
  switch (action.type) {
    case FETCH_BENEFIT: {
      return action.payload
    }
    default:
      return state;
  }
}

【问题讨论】:

  • initialValues 包含带有键 Field.name 的 Object
  • redux 键值是否与您字段中的名称完全相同?
  • 你能告诉我们你的减速器吗?

标签: javascript reactjs redux redux-form


【解决方案1】:

除非您告诉它,否则您的组件不会在 props 更改时重新渲染(您的 Redux 状态将在组件的 props 中)。一种方法是首先将您的数据设置为null 状态,在componentWillMount() 中获取它,使用getDerivedStateFromProps(),然后从状态中渲染它。

static getDerivedStateFromProps(props, state) {
  if (props.intialValues !== state.initialValues) {
    return { ...state, initialValues };
  }     

  return null;
}

【讨论】:

  • 一开始我也是这么想的,但是貌似他的组件是无状态的。
  • 您好,感谢您的回复。我对 React 有点陌生,但我的理解是 Redux 表单没有捕获初始值。即使我设置任意值而不发出异步获取请求也是如此。例如,如果我在 mapStateToProps 函数中传递 initialValues = {frequency: 'monthly'},表单不会显示它。
猜你喜欢
  • 2017-07-31
  • 2021-07-22
  • 2016-09-04
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 2017-08-19
  • 2016-04-14
  • 2017-10-24
相关资源
最近更新 更多