2017-02-22 24 views
1

Ich habe gerade angefangen zu experimentieren mit reagieren und Redux und ich habe einige Probleme auf dem Weg.reagieren mit redux und react-Router löst Aktion zweimal

Wenn ich versuche, asynchrone Daten bei der Routenänderung zu rendern, wird die ausgeführte Aktion zweimal ausgelöst. Zuerst ist undefiniert und dann kommen die echten Daten.

Hier ist mein Speicher

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; 

Minderer

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; 

Aktionen

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

und hier ist meine Komponente

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

was mache ich falsch?

console

Antwort

0

sagte Sie //this.props.profile on first is undefined and then filled

das, weil ist in der ersten machen, state.profileundefined ist, bis die Anforderung Antwort eintrifft und die setProfile Aktion ausgelöst wird.

Es gibt auch das Problem Andrew bemerkte, dass Sie dispatch(doneFetchingProfile) anrufen. Da du redux-thunk verwendest, löst das den Aufruf von doneFetchingProfile(dispatch, getState) aus, aber die Aktion HIDE_SPINNER wird niemals ausgelöst.


UPDATE: Es ist nichts falsch mit Ihrem Code. Sie können vor SHOW_SPINNER die Ausgabe von console.log(this.props) sehen und es gibt keine profile, weil es auch keinen profile Zustand gibt.

Dann, wenn Ihre Anfrage erfolgreich ist, wird profile in den Status gesetzt, dann an Ihre Komponente weitergegeben und dann können Sie im Protokoll sehen, dass profile gesetzt ist. Das sind keine Aktionen, dies ist das Protokoll Ihrer Requisiten.

Das erste Mal ist undefiniert, weil der im Reduzierer angegebene Anfangszustand {} ist (auch hier gibt es kein profile).

Wenn Sie

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

zu

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

ändern Sie werden sehen, dass die erste console.log(this.props)profile mit dem Wert 'some initial value' zeigen und dann an die Remote-Daten ändern.

+0

so versendete ich Versand (doneFetchingProfile (Profil)) und zurück Profil, aber auch so ist das gleiche. Wie reformiere ich den Code, der einmal mit den Daten ausgelöst werden soll? – fefe

+0

@fefe Ich verstehe es nicht. Wie schaust du, welche Aktionen versendet werden? Laut Code 'SET_PROFILE' sollte nur einmal gesendet werden. Aber 'state.profile' nimmt 2 Werte an: beginnt mit' undefiniert' und wird dann auf die korrekten Daten gesetzt, nachdem die obige Aktion ausgelöst wurde. – Lucas

+0

Ich habe einen Screenshot von der Konsole gemacht – fefe

0

Sie Dispatching 2 Aktionen

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

Erste von ihnen keine Daten haben, und es ist gesetzt tihs Aktion sehen aus wie einige Daten angeben und Ihre Komponente zu aktualisieren.

+0

Eigentlich, mit Redux-Thunk, das wird einfach keine Aktion in Bezug auf "Set-Profil" – Lucas

1

Dies ist, was hier passiert

  1. Ihre Komponente machen und zeigen undefined auf Konsole, weil es keine Profildaten ist so weit.
  2. Nach der Komponente mount rufen Sie componentDidmount auf, die eine Aktion auslösen, um Daten von der URL zu holen.

  3. Sie erhalten Daten von api und aktualisieren den Redux-Status, der auch Ihre Komponente aktualisiert.

  4. Deshalb rendern Funktion wird erneut aufgerufen und diesmal zeigt die Profildaten.

Es gibt nichts, zweimal zu versenden. Der Code ist völlig in Ordnung.

Verwandte Themen