如何从状态中获取 reduxFrom 的初始值?

How to get initialValues for a reduxFrom from state?

我正在使用带有 React redux 的表单。我有相同的表格来编辑和创建新表格。

我希望在打开我的表单时,如果进行编辑,我会输入来自我 api 的表单的初始值。

我已经尝试了官方文档,但它不起作用。

这是我的表格:

class Form extends Component {

  componentDidMount () {
    const tripId = this.props.match.params.uid;
    if(tripId){
      this.fetchData(tripId);
    }
  }

  fetchData = async (tripId) => {
    axios.defaults.headers.common['Authorization'] = 'token';
    axios.defaults.headers.common['Accept'] = 'application/vnd.trips.v1+json';
    await axios.get(`myurl`) 
    .then(res => {
      const trip = res.data;
      this.setState({ 
        trip: trip,
        isLoading: false,
        initialValues: trip
      });
    })
    console.log('Terminou de carregar')
  }

(....)
Form = reduxForm({ form: 'trip', enableReinitialize : true })(Form)
const mapStateToProps = state => {
  const { intl, vehicleTypes, users, dialogs, trip } = state

  return {
    intl,
    vehicleTypes,
    users,
    dialogs,
    initialValues: trip
  }
}

export default connect(
  mapStateToProps, { setDialogIsOpen }
)(injectIntl(withRouter(withTheme()(Form))))

但我的 initialValues 从未被填充,并且总是空白。我调试了代码,发现我的 API 正在加载并设置我的 fetchData 方法的状态。那么,我在这里做错了什么?

首先,您试图通过 this.setState 传递 initialValues 这是行不通的,reduxForm 期望 initialValues 作为 props 传递。

有一点要提一下,application statecomponent local state之间有一个区别,第一个-application state-显然是由redux管理的,另一个-local component state-是由 react 管理,您可以通过调用 this.setState

进行修改

所以要解决这个问题,您应该在收到来自 api 的数据时调度一个动作,并在 mapStateToProps

中更新您的道具

您的代码应如下所示:

class Form extends Component {

  componentDidMount () {
    const tripId = this.props.match.params.uid;
    if(tripId){
      this.fetchData(tripId);
    }
  }

  fetchData = async (tripId) => {
    await axios.get(`https://toptal-backend-fmaymone.c9users.io/trips/${tripId}`) 
    .then(res => {
      const trip = res.data;
      this.props.fillTheForm(trip);
    })
    console.log('Terminou de carregar')
  }

(....)
Form = reduxForm({ form: 'trip', enableReinitialize : true })(Form)
const mapStateToProps = state => {
  const { intl, vehicleTypes, users, dialogs, trip } = state

  return {
    intl,
    vehicleTypes,
    users,
    dialogs,
    initialValues: trip
  }
}

const fillTheForm = (dispatch) => (trip) => {
  // here you dispatch the action and update your application state
  // in your reducer when this action is dispatched,
  // then mapStateToProps should be called and the data you just
  // passed in your reducer should be in (state)
  dispatch()
}

export default connect(
  mapStateToProps, { setDialogIsOpen, fillTheForm }
)(injectIntl(withRouter(withTheme()(Form))))

正如@d7my 所说,您的错误是您试图通过 setState 更改 prop,它们在反应世界中是不同的东西。解决问题的最快方法是替换它:

this.setState({
   trip: trip,
   isLoading: false,
   initialValues: trip
});

对于:

this.props.initialize(trip)

道具 initialize 由 redux-form 导出到您的组件以更新表单初始状态。我做了一个 codesandbox 在那里你可以检查它是否工作。

也就是说,我认为您应该更改组件的结构,而不是将数据加载到组件 (componentDidMount) 中,您应该在 redux 操作中执行它,然后更新您的状态。这样做,您可以轻松地从 mapStateToProps 函数上的 redux 状态获取表单数据,并设置 initialValues prop 而不是使用 initialize props,这要好得多。