2017-09-25 63 views
1

假設一個具有下列組件文件HelloForm.jsx如何將數據異步加載到Redux中?

import React from 'react'; 
import {graphql} from 'react-apollo'; 
import {connect} from 'react-redux'; 
import {actions, Control, Form} from 'react-redux-form'; 
import {compose, withProps} from 'recompose'; 

import query from './HelloForm.gql'; 

const passThrough = fn => BaseComponent => props => { 
    fn(props, BaseComponent); 

    return BaseComponent(props); 
}; 

export const HelloForm = ({onSubmitEventHandler}) => 
    <Form 
      className="my-form" 
      model="forms.hello" 
      onSubmit={onSubmitEventHandler} 
    > 
     <label htmlFor="name">Name</label> 
     <Control.text 
      {...props} 
      model=".name" 
      id="name" 
     /> 

     <button type="submit">Say Hello</button> 
    </Form>; 

export const enhance = compose(
    connect(), 
    withProps({ 
     onSubmitEventHandler: ({name}) => { 
      window.alert(`Hello, ${name}`); 
     }, 
    }), 
    graphql(query), 
    passThrough(({data, dispatch, loading}) => { 
     if (!loading) { 
      dispatch(actions.load('forms.hello', data)); 
     } 
    }), 
); 

export default enhance(HelloForm); 

這似乎像預期的那樣工作,但一個得到以下警告:

警告:setState(...):現有的狀態轉換過程中無法更新(如render或其他組件的構造函數)。渲染方法應該是道具和狀態的純粹功能;構造函數的副作用是反模式,但可以移動到componentWillMount

然而,React's component documentation表明應該分派componentDidMount生命週期事件期間的動作(其可以與功能組件經由recompose.lifecycle來完成)。但是沒有道具提供給componentDidMount事件處理程序。

什麼是「異步」分派行動到Redux的正確方法?

+1

檢查是否有更新。我認爲它可以幫助你。 – lilezek

+0

@lilezek,如果我理解正確,[Redux-Saga](https://github.com/redux-saga/redux-saga),仍然需要以類似的方式向Redux發送一個動作。 –

+0

是的,當然。如果您使用Redux,則不會避免分派操作。佐賀幫助你讓Redux「不那麼純潔」。 – lilezek

回答

0

該解決方案確實使用recompose.lifecycle高階組件。但是,不能使用箭頭功能。更新的enchance高階組件應執行如下:

export const enhance = compose(
    connect(), 
    withProps({ 
     onSubmitEventHandler: ({name}) => { 
      window.alert(`Hello, ${name}`); 
     }, 
    }), 
    graphql(query), 
    lifecycle({ 
     componentDidMount: function() { 
      const {dispatch, loading, recipe} = this.props; 

      if (loading) { 
       dispatch(actions.load('forms.hello', data)); 
      } 
     }, 
    }), 
);