2017-02-22 15 views
1

私はちょうど反応と還元を試し始めました。途中でいくつかの問題に直面しています。reduxと反応し、反応ルータがアクションを2回送ります

ルート変更時に非同期データをレンダリングしようとすると、ディスパッチされたアクションが2度実行されています。最初は定義されておらず、実際のデータよりも優先されます。ここで

は私の店

import { createStore, combineReducers, applyMiddleware } from 'redux' 
import createLogger from 'redux-logger' 
import thunk from 'redux-thunk' 
import { routerReducer, routerMiddleware, push } from 'react-router-redux' 
import reducers from '../reducers' 
import { browserHistory } from 'react-router'; 

const middleware = [ thunk ]; 
if (process.env.NODE_ENV !== 'production') { 
    middleware.push(createLogger()); 
} 

middleware.push(routerMiddleware(browserHistory)); 


    // Add the reducer to your store on the `routing` key 
    const store = createStore(
     combineReducers({ 
      reducers, 
      routing: routerReducer 
     }), 
     applyMiddleware(...middleware), 

    ) 

    export default store; 

減速

export const RESOLVED_GET_PROFILE = 'RESOLVED_GET_PROFILE' 

const profileReducer = (state = {}, action) => { 
    switch (action.type) { 
     case 'SET_PROFILE': 
       return {profile: action.profile} 

     default: 
      return state; 
    } 
}; 

export default profileReducer; 

アクション

import * as types from './actionTypes'; 
import Api from '../middleware/Api'; 

export function getProfile() { 
    return dispatch => { 
     dispatch(setLoadingProfileState()); // Show a loading spinner 
     Api.get('profile').then(profile => { 
      dispatch(doneFetchingProfile); 
      dispatch(setProfile(profile)); 
     }).catch(error => { 
      dispatch(showError(error)); 
      throw(error); 
     }); 
    } 
} 

function setProfile(data) { 
    return { 
     type: types.SET_PROFILE, 
     profile: data 
    } 
} 


function setLoadingProfileState() { 
    return { 
     type: types.SHOW_SPINNER, 
     loaded: false 
    } 
} 

function doneFetchingProfile() { 
    return { 
     type: types.HIDE_SPINNER, 
     loaded: true 
    } 
} 

function showError() { 
    return { 
     type: types.SHOW_ERROR, 
     loaded: false, 
     error: 'error' 
    } 
} 

、ここでは私のコンポーネント

import React, {PropTypes, Component} from 'react'; 
import {bindActionCreators} from 'redux'; 
import {connect} from 'react-redux'; 
import * as profileActions from '../../../actions/profileActions'; 


class Profile extends Component { 

    static propTypes = { 
     profile: PropTypes.object.isRequired, 
    }; 

    constructor(props) { 
     super(props); 

     this.state = { 
      profile:{ 
       username: '', 
       password: '', 
       email: '' 
      } 
     } 
     this.onUpdate = this.onUpdate.bind(this) 
    } 

    onUpdate(event) { 
     alert() 
    } 

    componentDidMount() { 
     //here I dispatch the action 
     this.props.actions.getProfile() 
    } 

    componentWillReceiveProps(nextProps) { 

    } 

    render() { 
     console.log(this.props) 
     //this.props.profile on first is undefined and then filled 
     const { profile } = this.props.profile 

     return (
      <div> 

      </div> 
     ); 
    } 
} 

function mapStateToProps(state) { 

    return { 
     profile: state.default.profile, 
    }; 
} 

function mapDispatchToProps(dispatch) { 
    return { 
     actions: bindActionCreators(profileActions, dispatch) 
    }; 
} 

export default connect(mapStateToProps, mapDispatchToProps)(Profile); 
です

どうしたらいいですか?

console

答えて

0

あなたが最初にレンダリングするためです//this.props.profile on first is undefined and then filled

を述べ、state.profileは、undefinedです。

また、Andrew氏は、あなたがdispatch(doneFetchingProfile)と呼んでいると指摘しました。あなたはredux-thunkを使用しているので、それはdoneFetchingProfile(dispatch, getState)を呼び出すトリガーとなりますが、アクションHIDE_SPINNERは決してディスパッチされません。


UPDATE:あなたのコードに問題はありません。 SHOW_SPINNERの前にはconsole.log(this.props)の出力が表示され、profileも存在しないため、profileはありません。

要求が成功すると、profileが状態に設定され、コンポーネントに渡され、ログにprofileが設定されていることがわかります。それらは派遣されたアクションではなく、これはあなたの小道具のログです。

レデューサーで宣言されている初期状態が{}profileもあります)であるため、最初は未定義です。

あなたは

const profileReducer = (state = {}, action) => { 

const profileReducer = (state = {profile: 'some initial value'}, action) => { 

に変更する場合は、最初の console.log(this.props)が値 'some initial value'profileを表示し、リモートデータに変更されていることがわかります。

+0

に関する何らかのアクションを単に送出しないので、私はdispatch(doneFetchingProfile(profile))と返信プロファイルを試してみましたが、それは同じです。コードを一度データでリファクタリングするにはどうすればよいですか? – fefe

+0

@fefeわかりません。あなたはどのような行動が派遣されているのか見ていますか?コードによると 'SET_PROFILE'は一度だけディスパッチされるべきです。しかし、 'state.profile'は2つの値をとります:上記のアクションが送出された後、' undefined'で始まり、次に正しいデータに設定されます。 – Lucas

+0

コンソールからスクリーンショットを作成しました – fefe

0

あなたは2つのアクションそれらの最初にデータがない

dispatch(doneFetchingProfile); 
dispatch(setProfile(profile)); 

を派遣し、それはいくつかのデータを述べると、あなたのコンポーネントを更新するように設定tihsアクションのように見えるのです。要求応答が到着し setProfileアクションがディスパッチされるまで

+0

実際には、 "set profile" – Lucas

1

これはここ

  1. あなたのコンポーネントを何が起こっているかをレンダリングし、何のプロファイルデータは今のところ存在しないため、コンソール上未定義を示しました。
  2. コンポーネントのマウント後、urlからデータをフェッチするアクションを起動するcomponentDidmountを呼び出します。

  3. apiからデータを取得し、コンポーネントを更新するredux状態を更新します。

  4. したがって、レンダリング関数が再度呼び出され、今回はにプロファイルデータが表示されます。

2回のディスパッチはありません。コードは完璧です。

関連する問題