96 votes

Quand les bindActionCreators seraient-ils utilisés dans react/redux ?

Redux documents pour bindActionCreators déclare que :

Le seul cas d'utilisation de bindActionCreators est lorsque vous voulez passer des créateurs d'action à un composant qui n'est pas au courant de Redux, et vous ne voulez pas lui passer le dispatch ou le magasin Redux.

Quel serait un exemple où bindActionCreators seraient utilisés/besoins ?

Quel type de composant ne serait pas au courant Redux ?

Quels sont les avantages/inconvénients des deux options ?

//actionCreator
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
  return {
    posts: state.posts,
    comments: state.comments
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch)
}

vs

function mapStateToProps(state) {
  return {
    posts: state.posts,
    comments: state.comments
  }
}

function mapDispatchToProps(dispatch) {
  return {
    someCallback: (postId, index) => {
      dispatch({
        type: 'REMOVE_COMMENT',
        postId,
        index
      })
    }
  }
}

64voto

Diana Suvorova Points 431

Je ne pense pas que la réponse la plus populaire réponde réellement à la question.

Tous les exemples ci-dessous font essentiellement la même chose et suivent le concept d'absence de "préliaison".

// option 1
const mapDispatchToProps = (dispatch) => ({
  action: () => dispatch(action())
})

// option 2
const mapDispatchToProps = (dispatch) => ({
  action: bindActionCreators(action, dispatch)
})

// option 3
const mapDispatchToProps = {
  action: action
}

Option #3 est juste un raccourci pour l'option #1 donc la vraie question est de savoir pourquoi on utiliserait l'option #1 vs option #2 . J'ai vu les deux utilisés dans la base de code de react-redux, et je trouve que c'est plutôt confus.

Je pense que la confusion vient du fait que toutes les exemples en react-redux La doc utilise bindActionCreators tandis que le doc pour bindActionCreators (comme cité dans la question elle-même) dit de ne pas l'utiliser avec react-redux.

Je suppose que la réponse est la cohérence dans la base de code, mais personnellement je préfère envelopper explicitement les actions dans des expédition chaque fois que nécessaire.

3 votes

Comment est l'option #3 un raccourci pour l'option #1 ?

1 votes

0 votes

@ArtemBernatskyi Merci. Donc, il s'avère qu'il y a 3 cas pour mapDispatchToProps : function , object et disparus. La façon de traiter chaque cas est définie ici

48voto

markerikson Points 442

99% du temps, il est utilisé avec le React-Redux. connect() dans le cadre de la fonction mapDispatchToProps paramètre. Il peut être utilisé explicitement à l'intérieur de l'élément mapDispatch que vous fournissez, ou automatiquement si vous utilisez la syntaxe de raccourci d'objet et passez un objet rempli de créateurs d'action à la fonction connect .

L'idée est qu'en liant à l'avance les créateurs d'action, le composant que vous passez à la fonction connect() techniquement, il ne sait pas qu'il est connecté - il sait juste qu'il doit fonctionner. this.props.someCallback() . D'autre part, si vous n'avez pas lié les créateurs d'actions, et que vous avez appelé this.props.dispatch(someActionCreator()) maintenant le composant "sait" qu'il est connecté parce qu'il s'attend à ce que props.dispatch d'exister.

J'ai écrit quelques réflexions sur ce sujet dans mon billet de blog Idiomatic Redux : Pourquoi utiliser des créateurs d'actions ? .

1 votes

Mais il est connecté à 'mapDispatchToProps', ce qui est bien. Il semble que lier les créateurs d'actions soit en fait une chose négative/inexistante puisque vous perdrez la définition de la fonction (TS ou Flow) parmi de nombreuses autres choses comme le débogage. Sur mes projets les plus récents, je ne l'utilise jamais et je n'ai pas eu de problème à ce jour. J'utilise également Saga et l'état persistant. De plus, si vous appelez simplement des fonctions redux (vous obtenez cependant un clic agréable), je dirais que c'est encore plus propre que d'attacher des créateurs d'actions qui, à mon avis, sont désordonnés et inutiles. Vos smart (généralement des composants d'écran) peuvent toujours utiliser connect, mais seulement pour les props.

19voto

Charlie 木匠 Points 486

Exemple plus complet, passez un objet rempli de créateurs d'actions à connecter :

import * as ProductActions from './ProductActions';

// component part
export function Product({ name, description }) {
    return <div>
        <button onClick={this.props.addProduct}>Add a product</button>
    </div>
}

// container part
function mapStateToProps(state) {
    return {...state};
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        ...ProductActions,
    }, dispatch);
}

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

0 votes

Ceci devrait être la réponse

16voto

sansegot Points 103

Je vais essayer de répondre aux questions initiales ...

Composants intelligents et stupides

Dans votre première question, vous demandez essentiellement pourquoi bindActionCreators est nécessaire en premier lieu, et quel type de composants ne devrait pas être au courant de Redux.

En résumé, l'idée est que les composants doivent être divisés en deux parties. intelligent (conteneur) et stupide (de présentation). Composants muets travailler sur la base du besoin de savoir. Leur tâche essentielle est de rendre des données données en HTML et rien de plus. Ils ne doivent pas être au courant du fonctionnement interne de l'application. Ils peuvent être considérés comme la couche frontale de votre application.

D'autre part composants intelligents sont en quelque sorte une colle, qui prépare les données pour les stupide et, de préférence, n'effectue pas de rendu HTML.

Ce type d'architecture favorise un couplage lâche entre la couche d'interface utilisateur et la couche de données sous-jacente. Cela permet de remplacer facilement l'une des deux couches par une autre (par exemple, une nouvelle conception de l'interface utilisateur), sans que l'autre couche ne soit détruite.

Pour répondre à votre question : les composants muets ne devraient pas être au courant de Redux (ou de tout autre détail d'implémentation inutile de la couche de données, d'ailleurs) parce que nous pourrions vouloir le remplacer par autre chose à l'avenir.

Vous pouvez trouver plus d'informations sur ce concept dans le Manuel Redux et plus en profondeur dans l'article Composants de la présentation et du conteneur par Dan Abramov.

Quel exemple est le meilleur

La deuxième question portait sur les avantages/inconvénients des exemples donnés.

En el premier exemple les créateurs de l'action sont définis dans un actionCreators ce qui signifie qu'ils peuvent être réutilisés ailleurs. C'est à peu près la façon standard de définir les actions. Je ne vois pas vraiment d'inconvénients à cela.

En deuxième exemple définit les créateurs d'actions en ligne, ce qui présente de multiples inconvénients :

  • les créateurs d'actions ne peuvent pas être réutilisés (évidemment)
  • la chose est plus verbeuse, ce qui se traduit par une lecture moins aisée.
  • Les types d'action sont codés en dur - il est préférable de les définir en tant que consts séparément, afin qu'ils puissent être référencés dans les réducteurs - cela réduirait les risques d'erreurs de frappe.
  • la définition des créateurs d'actions en ligne est contraire à la manière recommandée/attendue de les utiliser - ce qui rendra votre code un peu moins lisible pour la communauté, au cas où vous prévoyez de partager votre code.

Le deuxième exemple a un avantage plutôt que le premier - c'est plus rapide à écrire ! Donc, si vous n'avez pas de grands projets pour votre code, cela pourrait être parfait.

J'espère avoir réussi à clarifier un peu les choses ...

0voto

tomc Points 216

Un bon cas d'utilisation pour bindActionCreators est destiné à l'intégration avec redux-saga en utilisant redux-saga-routines . Par exemple :

// routines.js
import { createRoutine } from "redux-saga-routines";
export const fetchPosts = createRoutine("FETCH_POSTS");

// Posts.js
import React from "react";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { fetchPosts } from "routines";

class Posts extends React.Component {
  componentDidMount() {
    const { fetchPosts } = this.props;
    fetchPosts();
  }

  render() {
    const { posts } = this.props;
    return (
      <ul>
        {posts.map((post, i) => (
          <li key={i}>{post}</li>
        ))}
      </ul>
    );
  }
}

const mapStateToProps = ({ posts }) => ({ posts });
const mapDispatchToProps = dispatch => ({
  ...bindActionCreators({ fetchPosts }, dispatch)
});

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

// reducers.js
import { fetchPosts } from "routines";

const initialState = [];

export const posts = (state = initialState, { type, payload }) => {
  switch (type) {
    case fetchPosts.SUCCESS:
      return payload.data;
    default:
      return state;
  }
};

// api.js
import axios from "axios";

export const JSON_OPTS = { headers: { Accept: "application/json" } };
export const GET = (url, opts) =>
  axios.get(url, opts).then(({ data, headers }) => ({ data, headers }));

// sagas.js
import { GET, JSON_OPTS } from "api";
import { fetchPosts } from "routines";
import { call, put, takeLatest } from "redux-saga/effects";

export function* fetchPostsSaga() {
  try {
    yield put(fetchPosts.request());
    const { data } = yield call(GET, "/api/posts", JSON_OPTS);
    yield put(fetchPosts.success(data));
  } catch (error) {
    if (error.response) {
      const { status, data } = error.response;
      yield put(fetchPosts.failure({ status, data }));
    } else {
      yield put(fetchPosts.failure(error.message));
    }
  } finally {
    yield put(fetchPosts.fulfill());
  }
}

export function* fetchPostsRequestSaga() {
  yield takeLatest(fetchPosts.TRIGGER, fetchPostsSaga);
}

Notez que ce modèle pourrait être mis en œuvre en utilisant Crochets React (à partir de React 16.8).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X