web-dev-qa-db-fra.com

avoir plusieurs instances du même redux react réutilisable composants sur la même page/route

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

24
Rahul

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.

29
Michael Peyper

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

2
jony89

J'ai interprété la question comme signifiant:

  • vous avez des données de contenu dans le magasin (par exemple, les sections et leurs titres)
  • vous avez des composants pour dessiner des bits des données (par exemple, votre <SectionHeader />)
  • vous voulez afficher plus d'une section sur une page mais tous vos en-têtes ont actuellement le même texte

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} />
0
Simon Dell