web-dev-qa-db-fra.com

Pourquoi mes accessoires sont-ils `undefined` lors de l’utilisation de redux et de react.js?

J'ai essayé d'ajouter à mon application un état qui vient d'enregistrer un booléen lorsqu'un événement est passé. Je ne peux pas comprendre ce que je fais mal ici.

Réducteur:  

import * as actionTypes from '../constants/action-types.js';

const initialState = [{
  eventPassed: false
}];

export default function eventPassed(state = initialState, action) {
  switch (action.type) {
    case actionTypes.EVENT_PASSED:
      return true;
    default:
      return state;
  }
}

Action:  

import * as actionTypes from '../constants/action-types';

export function eventPassed(eventPassed) {
  return {
    type: actionTypes.EVENT_PASSED,
    payload: { eventPassed: eventPassed }
  };
}

Conteneur autour du composant:  

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Example from '../components/example.jsx';
import { eventPassed } from '../actions/app-actions';

class ExampleContainer extends Component {
  render() {
    return (
      <Example {...this.props} />
    );
  }
}

const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators({
    eventPassed
  }, dispatch)
});

const mapStateToProps = (state) => ({
  eventPassed: state.eventPassed
});

export default connect(mapStateToProps, mapDispatchToProps)(ExampleContainer);

Composant:  

import React, { Component, PropTypes } from 'react';

class Example extends Component {

  constructor() {
    super();
    this.action = this.action.bind(this);
  }

  componentDidMount() {
    this.props.actions.eventPassed(true);
  }

  action() {
    console.log(this.props.eventPassed);
  }

  render() {
    return (
      <div>
        <button onClick={this.action}>Action</button>
      </div>
    );
  }
}

export default Example;

Lorsque j'essaie de me connecter "this.props.eventPassed" dans le composant<Example />, cela me donne " undefined ". Est-ce qu'il manque quelque chose? Cela semble être l'utilisation la plus simple du magasin dans Redux. 

6
Jim Peeters

Pourquoi this.props.eventPassed est-il enregistré comme "non défini" ?:

La fonction d'action (eventPassed) à laquelle vous essayez d'accéder à ce stade n'existe pas à this.props.actions.eventPassed. Il existe réellement uniquement sur this.props.actions.

En effet, vous avez lié la méthode d'action à la valeur 'actions' dans votre mapDispatchToProps. Ceci est à son tour donne accès à la Action eventPassed via this.props.actions.

Puisque this.props.actions pointe sur eventPassed, en essayant d'accéder à this.props.actions.eventPassed vous essayez d'accéder à la propriété de 'eventPassed' sur l'action eventPassed. Le résultat est que quand vous vous connectez pour cette propriété, vous recevez "undefined"


Autres amendements nécessaires:

mapDispatchToProps doit renvoyer une valeur

Une fonction flèche avec un corps de bloc ne renvoie pas automatiquement une valeur et doit donc être définie. Donc, votre fonction doit ressembler à:

mapDispatchToProps = (dispatch) => {
  return { actions: bindActionCreators(eventPassed, dispatch) }
} 

Etat initial est un tableau contenant un objet:

const initialState = [{
  eventPassed: false
}];

Puisque vous essayez de le référencer plus tard en tant que object { eventPassed: true} et non un tableau d'objets [ { eventPassed: true } ], il devrait être:

const initialState = {
  eventPassed: false
};

Le réducteur doit renvoyer l'état correct mis à jour (mais non muté _): 

export default function eventPassed(state = initialState, action) {
  switch (action.type) {
    case actionTypes.EVENT_PASSED:
      return {
        ...state,
        eventPassed: action.payload
      };
    default:
      return state;
  }
}

Ce que vous faisiez initialement était de retourner un état qui n'était plus un objet (ou dans le cas initial un tableau d'objet) mais simplement la valeur de true

9
Pineda

Dans votre reducer vous initialisez votre état avec un tableau d'objet a la propriété eventPassed, vous ne retournez que le booléen, ce qui est incorrect car il remplace l'état initial, l'initState peut donc être simplement un objet contenant le booléen sur la base de la payload envoyée avec l'action décrite comme suit:

import * as actionTypes from '../constants/action-types.js';

const initialState = {
  eventPassed: false
};

export default function eventPassed(state = initialState, action) {
  switch (action.type) {
    case actionTypes.EVENT_PASSED:
      return {
        ...state,
        eventPassed: action.payload
      };
    default:
      return state;
  }
}

De plus, dans votre component, vous devrez peut-être changer:

this.props.eventPassed à this.props.actions.eventPassed

1
Basim Hennawi