从状态以Redux格式加载初始值

时间:2018-07-23 13:26:45

标签: javascript reactjs redux redux-form

我试图在Redux表单中加载初始值(从异步调用到服务器)。 服务器调用可以正常工作(我可以看到我的redux状态正在更新),但是表单不显示值。

我阅读了有关堆栈溢出的所有问题,并应用了所有解决方案,但无济于事:

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

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

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

1 个答案:

答案 0 :(得分:0)

您的组件不会在道具更改时重新渲染(您的Redux状态将在组件的道具中),除非您告知。一种实现方法是,首先将状态为null的数据置于状态,在componentWillMount()中进行获取,使用getDerivedStateFromProps(),然后从状态进行渲染。

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

  return null;
}