Nous créons une grande application frontale.
Nous utilisons React-Redux pour cela
Nous créons des composants réutilisables.
** Cette question concerne le fait d'avoir plusieurs instances des mêmes composants redux react réutilisables sur la même page/route **
Détails du problème:
Nous avons un composant Sectionheader. Ce qui est lié à l’état redux.
Il écoute le réducteur de propriétés d'en-tête SectionheaderReducer.
Comme nous avons 2 instances de cet en-tête de section sur la page, les deux ont tendance à afficher les mêmes valeurs, car elles sont liées à la même propriété state store.
Comment rendre le composant réactif réutilisable basé sur redux configurable. Ainsi, chaque instance peut avoir une valeur différente de la propriété header pour réducteur SectionheaderReducer
Vous devez implémenter un moyen de nommer les instances. Cela peut être aussi élémentaire que de passer une clé pour différencier les composants et les réducteurs.
Vous pouvez utiliser la variable ownProps
dans votre fonction mapStateToProps
pour guider le mappage vers un espace de noms.
const mapStateToProps = (state, ownProps) {
let myState = state[ownProps.namespace]
return {
myState.value
}
}
La même méthode peut être utilisée pour transmettre un espace de nom à la variable mapDispatchToProps
const mapDispatchToProps = (dispatch, ownProps) {
return {
myAction: (myParam) => dispatch(myAction(ownProps.namespace, myParam))
}
}
Rappelez-vous simplement d'utiliser l'espace de nom dans le type d'action pour que les réducteurs ne marchent pas sur les orteils
const myAction => (namespace, myParam) {
return { type: `${namespace}/${MY_TYPE_CONSTANT}`, myParam }
}
Et assurez-vous que le réducteur est un espace de noms aussi
const myReducer = (namespace) => (state = initialState, action) => {
switch(action.type) {
case `${namespace}/${MY_TYPE_CONSTANT}`:
return { ...state, action.myParam }
default:
return state
{
}
Ajoutez maintenant les 2 réducteurs de noms lorsque vous combinez des réducteurs.
combineReducers({
myInstance1 : myReducer('myInstance1')
myInstance2 : myReducer('myInstance2')
}
Enfin, passez l'espace de noms à chaque instance
render() {
return (
<div>
<MyComponent namespace='myInstance1' />
<MyComponent namespace='myInstance2' />
</div>
)
}
Avertissement: Je suis le contributeur principal de la bibliothèque suivante.
redux-subspace peut fournir une implémentation plus sophistiquée du namespacing sans avoir à réimplémenter ce modèle pour chaque composant pour lequel vous souhaitez avoir plusieurs instances.
La création des réducteurs est similaire à celle décrite ci-dessus.
const reducer = combineReducers({
myInstance1: namespaced('myInstance1')(myReducer)
myInstance2: namespaced('myInstance2')(myReducer)
})
Alors SubspaceProvider
peut être utilisé pour changer l'état de chaque composant
render() {
return (
<div>
<SubspaceProvider mapState={state => state.myInstance1} namespace='myInstance1'>
<MyComponent />
</SubspaceProvider>
<SubspaceProvider mapState={state => state.myInstance2} namespace='myInstance2'>
<MyComponent />
</SubspaceProvider>
</div>
)
}
Assurez-vous simplement de changer également votre fonction mapStateToProps
pour commencer à traverser à partir de la sous-arborescence mappée dans le fournisseur.
const mapStateToProps = (state) {
return {
state.value
}
}
Il existe également un composant d'ordre supérieur si vous préférez réduire l'imbrication.
Je l'ai implémenté d'une manière différente, sans changer réellement le nom de l'action avec un espace de nom.
J'ai plutôt ajouté des fonctions infra qui intercepteront les créateurs d'action et ajouteront meta-data
à chaque action. (suivant FSA
) Ainsi, vous n'avez pas besoin de changer votre réducteur ou la fonction mapStateToProps
.
En outre, il est compatible avec redux-thunk
.
Devrait être facile à utiliser ... réducteur-action-intercepteur
J'ai interprété la question comme signifiant:
<SectionHeader />
)Une solution possible consisterait à ajouter l’idée de "sections" à votre magasin. Vous créeriez des réducteurs qui gèrent la structure du contenu des données. PAR EXEMPLE. l'état du magasin, à un moment donné, peut ressembler à ceci:
{
sections: {
0: {
header: 'My section title',
content: 'Whatever your content is'
},
1: {
header: 'My other section title',
content: 'Loads of lovely writing or hrefs to images or whatever'
}
}
}
`` `
Vous auriez alors un "composant conteneur" ou un "composant de mise en page" ou un "composant intelligent" (ils portent plusieurs noms), qui "sait" que vous souhaitez utiliser les sections 2 et 4 sur une page particulière. Comment ça le sait, c'est à vous. Peut-être que vous codez en dur les index (car ce sera toujours le même), peut-être avez-vous une règle de filtrage, peut-être avez-vous un autre champ dans le magasin qui définit les choix ... etc.
Le composant conteneur transmettrait alors l'en-tête choisi au "muet", peut-être comme ceci:
<SectionHeader>{sections[2].header}</SectionHeader>
ou
<SectionHeader title={sections[2].header} />