2016-11-22 5 views
0

Wo genau sollte ich mit dem Problem umgehen, dass diese Komponente nicht mit dem gewünschten state geladen wird?Wie Eigenschaften von Objekten in React rendern?

Mein Render-Methode den folgenden Fehler verursacht ...

Uncaught TypeError: Cannot read property 'email' of undefined 

... obwohl die JSON.stringify Linie zeigt mir, dass die E-Mail-Eigenschaft hat (schließlich) existieren.

Die console.log down in mapStateToProps bestätigt, dass der Zustand zunächst ohne die Eigenschaft user geladen wird (wodurch der Fehler verursacht wird).

Siehe meinen naiven Versuch, dies in meiner Konstruktor-Methode zu lösen. Es funktioniert nicht.

Was ist der richtige Weg, um mit dieser Situation umzugehen? Einige bedingte innerhalb der Rendermethode? Versuchte das auch, aber immer noch kein Glück.

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

class Feature extends Component { 

    constructor(props){ 
     super(props); 
     this.state = { 
      'auth': { 
       'user':{ 
        email:'', 
        id:'' 
       } 
      } 
     } 
    } 

    componentWillMount() { 
     this.props.fetchMessage();  // puts the user object into state 
    } 

    render() { 
     return (
      <div className="feature"> 
       Here is your feature 
       {JSON.stringify(this.props.user , null, 2)} 
       {this.props.user.email} 
      </div> 
     ); 
    } 

} 

function mapStateToProps(state) { 
    console.log('state',state); 
    return { user: state.auth.user } 
} 

export default connect(mapStateToProps, actions)(Feature); 

/////////// Aktion /////////

export function fetchMessage(){ 

    return function(dispatch){ 
     axios 
      .get(ROOT_URL, { 
       headers: { 
        authorization: localStorage.getItem('token') 
       } 
      }) 
      .then((response) => { 
       dispatch({ 
        type: FETCH_MESSAGE, 
        payload: response.data.user 
       }) 
      }) 
    } 

} 

/////////////// // Minderer /////////////

var authReducer = (state={}, action) => { 
    console.log('action.payload',action.payload); 

    switch(action.type){ 
     case AUTH_USER: return  {...state, error: '', authenticated: true}; 
     case UNAUTH_USER: return {...state, error: '', authenticated: false}; 
     case AUTH_ERROR: return  {...state, error: action.payload}; 
     case FETCH_MESSAGE: return {...state, user: { 
                 email: action.payload.email, 
                 id: action.payload._id 
                }}; 
     default: return state; 
    }; 
}; 
+0

Es wäre es Ihnen leichter machen zu helfen, wenn Sie Ihre Aktionen und Reduzierungen Code hinzufügen könnte. – jpdelatorre

+0

getan - aber meine JSON.stringify Zeile sagt mir, dass der Zustand korrekt aktualisiert wird. Es ist nur der Bruchteil einer Sekunde zwischen dem Laden von Komponenten und dem Aktualisieren des Zustands, der mir das Problem verursacht. – dwilbank

Antwort

2

Redux nutzt ein globalen Zustand genannt store, die außerhalb Ihrer Komponente lebt. In Ihrem constructor haben Sie eine this.state = {...} Anweisung. Dies ist ein lokaler Status, der nur für die Komponente Feature verfügbar ist.

connect von react-redux verbindet im Wesentlichen die Informationen innerhalb der store Ihrer Komponente props daher mapStateToProps genannt.

Bearbeiten Sie Ihre mapStateToProps um so etwas wie ...

function mapStateToProps(state) { 
    const { auth: { user = {} } = {}} = state; 
    return { 
     user 
    } 
} 

Was sie tut, ist zu versuchen, die user Eigenschaft aus dem Laden zu extrahieren, und wenn es noch nicht vorhanden ist, um es zu leeres Objekt gesetzt. Ihr Fehler ist darauf zurückzuführen, dass Ihr mapStateToProps auf die Benutzereigenschaft zugreift, die noch nicht vorhanden ist. Möglicherweise möchten Sie einen Standardwert als initialState festlegen, um dieses Problem zu vermeiden.

+0

OK - Ihr Code hat funktioniert, aber das ist eine intensive Destrukturierung, die mich ein paar Minuten dauern wird! Dein letzter Satz, der den Ausgangszustand festlegte, schien einfacher zu sein. In welchem ​​Stadium würde ich das tun? Zurück wo verwende ich createStoreWithMiddleware? – dwilbank

+0

Ja, Sie legen den Anfangszustand in Ihrem Erstellungsspeicher fest. – jpdelatorre

+0

Nicht in der ersten Zeile meines AuthReducer? – dwilbank

2

Also hier ist was passiert .. Sie machen eine Server-Anfrage für ein user Objekt und bei Erfolg wird das empfangene Objekt in Ihrem Redux-Shop gespeichert. Während der Durchführung einer solchen Aktion die Komponente wiedergegeben wird, wie folgt:

  1. Sie haben die Anfrage an den Server initiiert, die zur Zeit bedeutet, dass kein user in Ihrem Geschäft ist und so wird das Bauteil mit this.props.userundefined gemacht.
  2. Ihre Anfrage ist erfolgreich und das Objekt user ist in Ihrem Geschäft gespeichert. Wenn das passiert, wird react-redux Ihre Komponente mit dem Benutzerobjekt erneut rendern und this.props.user ist in Ihrer Komponente verfügbar.

    Während der ersten Schritt seit this.props.user nicht verfügbar ist, erhalten Sie einen Fehler beim Zugriff auf this.props.user.email. Obwohl die Antwort von @jpdelatorre ziemlich gut ist, können Sie einfach Ihre Rendermethode einchecken.

    render() { 
        let user = this.props.user || {}; 
        .... 
         {user.email} 
        .... 
    } 
    
+0

danke für die alternative lösung sir – dwilbank

+0

Glücklich zu helfen! :) –

Verwandte Themen