Je lisais la documentation de la bibliothèque Redux et elle a cet exemple:
En plus de lire l'état, les composants de conteneur peuvent envoyer des actions. De la même manière, vous pouvez définir une fonction appelée
mapDispatchToProps()
qui reçoit la méthodedispatch()
et renvoie les accessoires de rappel que vous souhaitez injecter dans le composant de présentation.
Cela n'a aucun sens. Pourquoi avez-vous besoin de mapDispatchToProps
alors que vous avez déjà mapStateToProps
?
Ils fournissent également cet exemple de code pratique:
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
Quelqu'un peut-il expliquer en termes simples comment cette fonction est et pourquoi elle est utile?
Je pense qu'aucune des réponses n'a cristallisé la raison pour laquelle mapDispatchToProps
est utile.
On ne peut vraiment répondre à cette question que dans le contexte du modèle container-component
, que j'ai mieux compris en première lecture: Container Components alors tilisation avec React .
En un mot, vos components
sont censés se préoccuper uniquement d’afficher des éléments. Le seul endroit où ils sont supposés obtenir des informations est leur accessoire .
Séparer de "l'affichage des éléments" (composants) est:
C’est ce que sont les containers
.
Par conséquent, un "bien conçu" component
dans le motif ressemble à ceci:
class FancyAlerter extends Component {
sendAlert = () => {
this.props.sendTheAlert()
}
render() {
<div>
<h1>Today's Fancy Alert is {this.props.fancyInfo}</h1>
<Button onClick={sendAlert}/>
</div>
}
}
Voyez comment ce composant récupère les informations qu'il affiche des accessoires (provenant du magasin redux via mapStateToProps
) et obtient également sa fonction d'action de ses accessoires: sendTheAlert()
.
C'est là que mapDispatchToProps
entre: dans le container
correspondant
// FancyButtonContainer.js
function mapDispatchToProps(dispatch) {
return({
sendTheAlert: () => {dispatch(ALERT_ACTION)}
})
}
function mapStateToProps(state) {
return({fancyInfo: "Fancy this:" + state.currentFunnyString})
}
export const FancyButtonContainer = connect(
mapStateToProps, mapDispatchToProps)(
FancyAlerter
)
Je me demande si vous pouvez voir, maintenant que c’est la container
1 qui connaît Redux, dispatch, store and state et ... des trucs.
La component
du motif, FancyAlerter
, qui effectue le rendu, n'a pas besoin de savoir quoi que ce soit de ce genre de choses: elle appelle sa méthode à l'appel à onClick
du bouton, via son les accessoires.
Et ... mapDispatchToProps
était le moyen utile fourni par redux pour permettre au conteneur de passer facilement cette fonction au composant encapsulé sur ses accessoires.
Tout cela ressemble beaucoup à l'exemple de todo dans la documentation, et à une autre réponse ici, mais j'ai essayé de l'exprimer à la lumière du motif pour souligner pourquoi .
(Remarque: vous ne pouvez pas utiliser mapStateToProps
dans le même but que mapDispatchToProps
pour la raison fondamentale pour laquelle vous n'avez pas accès à dispatch
à l'intérieur de mapStateToProp
. 'pas utiliser mapStateToProps
pour donner au composant encapsulé une méthode qui utilise dispatch
.
Je ne sais pas pourquoi ils ont choisi de le diviser en deux fonctions de mappage - il aurait peut-être été préférable d'avoir mapToProps(state, dispatch, props)
IE une fonction pour faire les deux!
1 Notez que j'ai délibérément appelé explicitement le conteneur FancyButtonContainer
, pour souligner qu'il s'agit d'une "chose" - l'identité (et donc l'existence!) Du conteneur. comme "une chose" est parfois perdue dans le raccourci
export default connect(...)
syntaxe indiquée dans la plupart des exemples
C'est fondamentalement un raccourci. Donc au lieu d'avoir à écrire:
this.props.dispatch(toggleTodo(id));
Vous utiliseriez mapDispatchToProps comme indiqué dans votre exemple de code, puis vous écririez ailleurs:
this.props.onTodoClick(id);
ou plus probablement dans ce cas, vous auriez cela comme gestionnaire d'événement:
<MyComponent onClick={this.props.onTodoClick} />
Il y a ici une vidéo utile de Dan Abramov à ce sujet: https://egghead.io/lessons/javascript-redux-generating-containers-with-connect-from-react-redux-visibletodolist
mapStateToProps()
est un utilitaire qui aide votre composant à obtenir l'état mis à jour (qui est mis à jour par d'autres composants),mapDispatchToProps()
est un utilitaire qui aidera votre composant à déclencher un événement d'action (action de distribution pouvant entraîner un changement de l'état de l'application).
mapStateToProps
, mapDispatchToProps
et connect
à partir de la bibliothèque react-redux
fournit un moyen pratique d'accéder à votre fonction state
et dispatch
de votre magasin. Donc, fondamentalement, connect est un composant d'ordre supérieur, vous pouvez également penser comme un wrapper si cela vous semble judicieux. Ainsi, chaque fois que votre state
sera modifié, mapStateToProps
sera appelé avec votre nouveau state
et ultérieurement, lorsque vous _ props
le composant de mise à jour exécutera la fonction de rendu pour rendre votre composant dans le navigateur. mapDispatchToProps
stocke également les valeurs-clés sur le props
de votre composant; elles prennent généralement la forme d'une fonction. De cette manière, vous pouvez déclencher state
changement à partir de votre événement onClick
, onChange
de votre composant.
De docs:
const TodoListComponent = ({ todos, onTodoClick }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
)
const mapStateToProps = (state) => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
const TodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
Assurez-vous également que vous connaissez bien fonctions React stateless et composants d'ordre supérieur
mapStateToProps
reçoit les state
et props
et vous permet d'extraire des propriétés de l'état à transmettre au composant.
mapDispatchToProps
reçoit dispatch
et props
et vous permet de lier les créateurs d'action à l'envoi afin que l'action soit envoyée lorsque vous exécutez la fonction résultante.
Je trouve que cela vous évite seulement d'avoir à faire dispatch(actionCreator())
au sein de votre composant, ce qui le rend un peu plus facile à lire.
https://github.com/reactjs/react-redux/blob/master/docs/api.md#arguments
Supposons maintenant qu’il existe une action pour redux telle que:
export function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
Quand vous l'importez,
import {addTodo} from './actions';
class Greeting extends React.Component {
handleOnClick = () => {
this.props.onTodoClick(); // This prop acts as key to callback prop for mapDispatchToProps
}
render() {
return <button onClick={this.handleOnClick}>Hello Redux</button>;
}
}
const mapDispatchToProps = dispatch => {
return {
onTodoClick: () => { // handles onTodoClick prop's call here
dispatch(addTodo())
}
}
}
export default connect(
null,
mapDispatchToProps
)(Greeting);
Comme le nom de la fonction indique mapDispatchToProps()
, mappez dispatch
l'action sur les accessoires (les accessoires de notre composant)
Ainsi, prop onTodoClick
est une clé pour mapDispatchToProps
fonction qui délègue furthere à l’action d’envoi addTodo
.
Aussi, si vous voulez couper le code et contourner l’implémentation manuelle, vous pouvez le faire,
import {addTodo} from './actions';
class Greeting extends React.Component {
handleOnClick = () => {
this.props.addTodo();
}
render() {
return <button onClick={this.handleOnClick}>Hello Redux</button>;
}
}
export default connect(
null,
{addTodo}
)(Greeting);
Ce qui signifie exactement
const mapDispatchToProps = dispatch => {
return {
addTodo: () => {
dispatch(addTodo())
}
}
}