2015-11-16 25 views
9

Simile all'esempio ToDo per Redux, la struttura del mio progetto è simile, solo un contenitore con una serie di componenti figlio da visualizzare. Il negozio sarà simile alla seguente:Connessione nidificata Redux componenti smart con riduttori

{ 
    workspace: { 
     widgets: [1, 2, 3] 
    } 
    widgets: { 
     1: { 
      id: 1, 
      title: 'First Widget', 
      lastPrice: 123.324, 
      lastUpdate: '2015-11-12' 
     }, 
     2: { 
      id: 2, 
      title: 'Second Widget', 
      lastPrice: 1.624, 
      lastUpdate: '2015-11-12' 
     }, 
     3: { 
      id: 3, 
      title: 'Third Widget', 
      lastPrice: 4.345, 
      lastUpdate: '2015-11-12' 
     } 
    } 
} 

Ogni elemento widget è un componente complesso nel suo pieno diritto - un sacco di possibili azioni, molte proprietà, e molti componenti muti bambino. Quindi, ho reso ciascun widget un componente smart connesso con un WidgetReducer dedicato per mantenere separate le modifiche dello stato.

mi piacerebbe il WidgetReducer di essere interessato solo un widget alla volta, quindi lo stato gestito da esso sarebbe solo un singolo nodo widget di simile:

{ id: 3, 
    title: 'Third Widget', 
    lastPrice: 4.345, 
    lastUpdate: '2015-11-12' 
} 

mio componente Area di lavoro attualmente itera su tutti widget, passando il widget ID a ciascun componente intelligente widget:

@connect(state => ({ workspace: state.workspace })) 
export default class Workspace extends React.Component { 
    render() { 
     return (
      <div> 
       {this.props.workspace.widgets.map(id => 
        (<Widget key={id} widgetId={id} />) 
       )} 
      </div> 
     ); 
    } 
} 

mio componente widget è in questo modo:

@connect((state, ownProps) => ({ widget: state.widgets[ownProps.widgetId]})) 
export default class Widget extends React.Component { 
    componentWillMount() { 
     this.props.dispatch(subscribeToUpdates(this.props.widgetId)); 
    } 

    render() { 
     return (
      <div> 
       <header>{this.props.widget.title}</header> 
       <div> /* Other widget stuff goes here */</div> 
      </div> 
     ); 
    } 
} 

Come posso collegare ciascun componente Widget in modo che riceva solo gli aggiornamenti di stato sul proprio oggetto Widget, e il Widget Reducer connesso riguarda solo singoli oggetti Widget, piuttosto che una collezione di essi?

+0

Puoi approfondire un po '? Un riduttore non riceve lo stato, solo le azioni. La tua domanda è un po 'ambigua ... Potresti inviare un'azione che ha una proprietà che contiene le fette di dati di cui hai bisogno ... Non sei sicuro se questo è quello che vuoi. – Seneca

+0

Ho provato a chiarire ... fammi sapere se ancora non è chiaro! Grazie. – Marcus

+0

@Seneca voleva solo sottolineare che un riduttore è una pura funzione che accetta uno stato e un'azione e sputa un nuovo stato. https://github.com/rackt/redux#the-gist – Joe

risposta

4

Prima di tutto dare un'occhiata a Riseleziona: https://github.com/rackt/reselect

Se ho capito la domanda, questo è quello che state cercando. Diciamo che lo stato di widget-id 2 cambia, widget 1 e widget 3 non si preoccupano dello stato di widget-id 2 modificato. Solo il widget 2 deve riflettere questo cambiamento. Riseleziona ti dà il potere di creare funzioni di selezione "memoizzate". Può sembrare una parola di fantasia, ma in pratica significa che solo se il valore di input di un selettore cambia, verrà calcolato lo stato successivo.

Nell'esempio del widget, verranno create funzioni di selezione che ricalcolano lo stato solo se è stata modificata la porzione di stato interessata.

possibile esempio:

import { createSelector } from 'reselect' 

const widgetByIdSelector = (state, props) => state.widgets[props.widgetId] 
// this is the `input` function for you selector: as input we take the 
// specific slice of state a specific widgetId requests. 
// the main idea is: only if the `input` of this function changes, it'll 'reselect' that state. 

export const widgetSelector = createSelector(
    widgetByIdSelector, 
    (widgetById) => { 
     return { widgetById } 
    } 

@connect(widgetSelector) 
export default class Widget extends Component { ... } 

Non ho idea se questo codice funziona, ha scritto questo su un viaggio in treno con collegamento ad internet traballante, ma questo è l'idea principale ...

Per quanto riguarda un riduttore & creatori di azione (avrete probabilmente facendo qualcosa di simile):

export function createActionForSpecificWidgetById(widgetId, payload) { 
    return { 
     type: ACTIONS.HERE_COMES_YOUR_ACTION_TYPE, 
     widgetId, 
     payload 
    } 
} 

function reducer(state = initialState, action) { 
    switch(action.type) { 
    case HERE_COMES_YOUR_ACTION_TYPE: 
     //now you can modify the state of the specific widgetId because you have access to the id at action.widgetId 
} 

'questo quello che cercavi?

+0

Questo è piuttosto utile, e sì, Riseleziona sicuramente aiuterà.Tuttavia non risponde alla seconda parte della domanda: lo stato che viene passato e restituito dal riduttore, voglio essere un oggetto widget singolo, piuttosto che una raccolta di tutti i widget di cui ho bisogno per estrarre il mio specifico widget di ID. Sto iniziando a pensare che non sia davvero possibile? – Marcus

+0

Su ulteriore pensiero, ciò potrebbe essere tecnicamente possibile, ma sarebbe il caso di avere una raccolta di riduttori di widget, i cui risultati verrebbero quindi combinati in una raccolta di widget nello store (come descritto [nei documenti] (http://rackt.org/redux/docs/basics/DataFlow.html)). Non carino, e non necessario. Solo la mia comprensione per principianti su come funziona Redux in mostra :) – Marcus

+0

quindi vuoi combinareRiduttori ({widget: combinaRiduttori ({widget1: widgetReducer1, widget2: widgetReducer2, widget2: widgetReducer3}})? Ora il tuo stato sembra {widget: {widget1: {}, widget2: {}, widget3: {}} – Seneca

Problemi correlati