it-swarm.com.de

Verschachtelte Reduktionsminderer

Ist es möglich, Reduzierungen mit der folgenden Struktur zu kombinieren:

import 'user' from ...
import 'organisation' from ...
import 'auth' from ...
// ...

export default combineReducers({
  auth: {
    combineReducers({
        user,
        organisation,  
    }),
    auth,
  },
  posts,
  pages,
  widgets,
  // .. more state here
});

Wo der Staat die Struktur hat:

{
    auth: {
        user: {
            firstName: 'Foo',
            lastName: 'bar',
        }
        organisation: {
            name: 'Foo Bar Co.'
            phone: '1800-123-123',
        },
        token: 123123123,
        cypher: '256',
        someKey: 123,
    }
}

Wo die Variable auth die Struktur hat:

{
    token: 123123123,
    cypher: '256',
    someKey: 123,   
}

also ist vielleicht der Spread-Operator praktisch? ...auth nicht sicher :-(

42
AndrewMcLagan

Es ist vollkommen in Ordnung, Ihre verschachtelten Reduzierungen mit combineReducers zu kombinieren. Aber es gibt noch ein anderes Muster, das sehr praktisch ist: verschachtelte Reduzierstücke.

const initialState = {
  user: null,
  organisation: null,
  token: null,
  cypher: null,
  someKey: null,
}

function authReducer(state = initialState, action) {
  switch (action.type) {
    case SET_ORGANISATION:
      return {...state, organisation: organisationReducer(state.organisation, action)}

    case SET_USER:
      return {...state, user: userReducer(state.user, action)}

    case SET_TOKEN:
      return {...state, token: action.token}

    default:
      return state
  }
}

Im obigen Beispiel kann authReducer die Aktion an organisationReducer und userReducer weiterleiten, um einen Teil ihres Status zu aktualisieren.

54
Florent

Ich wollte nur ein wenig auf die sehr gute Antwort eingehen, die @Florent gegeben hat, und darauf hinweisen, dass Sie Ihre App auch ein wenig anders strukturieren können, um verschachtelte Reduktionen zu erreichen, indem Sie Ihre Root-Reduktion aus Reduktionen, die auch kombinierte Reduktionen sind, kombinieren

Zum Beispiel

// src/reducers/index.js
import { combineReducers } from "redux";
import auth from "./auth";
import posts from "./posts";
import pages from "./pages";
import widgets from "./widgets";

export default combineReducers({
  auth,
  posts,
  pages,
  widgets
});

// src/reducers/auth/index.js
// note src/reducers/auth is instead a directory 
import { combineReducers } from "redux";
import organization from "./organization";
import user from "./user";
import security from "./security"; 

export default combineReducers({
  user,
  organization,
  security
});

dies setzt eine etwas andere Zustandsstruktur voraus. Stattdessen wie folgt:

{
    auth: {
        user: {
            firstName: 'Foo',
            lastName: 'bar',
        }
        organisation: {
            name: 'Foo Bar Co.'
            phone: '1800-123-123',
        },
        security: {
            token: 123123123,
            cypher: '256',
            someKey: 123
        }
    },
    ...
}

@ Florents Ansatz wäre wahrscheinlich besser, wenn Sie die Statusstruktur nicht ändern können

33
Joseph Nields

Inspiriert durch die Antwort von @ florent habe ich festgestellt, dass Sie dies auch versuchen könnten. Nicht unbedingt besser als seine Antwort, aber ich denke, es ist etwas eleganter.

function userReducer(state={}, action) {
    switch (action.type) {
    case SET_USERNAME:
      state.name = action.name;
      return state;
    default:
      return state;
  }
} 

function authReducer(state = {
  token: null,
  cypher: null,
  someKey: null,
}, action) {
  switch (action.type) {
    case SET_TOKEN:
      return {...state, token: action.token}
    default:
      // note: since state doesn't have "user",
      // so it will return undefined when you access it.
      // this will allow you to use default value from actually reducer.
      return {...state, user: userReducer(state.user, action)}
  }
}
4
D.W

Beispiel (siehe attachNestedReducers unten)

import { attachNestedReducers } from './utils'
import { profileReducer } from './profile.reducer'
const initialState = { some: 'state' }

const userReducerFn = (state = initialState, action) => {
  switch (action.type) {
    default:
      return state
  }
}

export const userReducer = attachNestedReducers(userReducerFn, {
  profile: profileReducer,
})

Zustandsobjekt 

{
    some: 'state',
    profile: { /* ... */ }
}

Hier ist die Funktion

export function attachNestedReducers(original, reducers) {
  const nestedReducerKeys = Object.keys(reducers)
  return function combination(state, action) {
    const nextState = original(state, action)
    let hasChanged = false
    const nestedState = {}
    for (let i = 0; i < nestedReducerKeys.length; i++) {
      const key = nestedReducerKeys[i]
      const reducer = reducers[key]
      const previousStateForKey = nextState[key]
      const nextStateForKey = reducer(previousStateForKey, action)
      nestedState[key] = nextStateForKey
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    return hasChanged ? Object.assign({}, nextState, nestedState) : nextState
  }
}
0
Andrew Luca