wake-up-neo.net

Wie kann man auf den Status in Redux Reducer zugreifen?

Ich habe einen Reduzierer, und um den neuen Zustand zu berechnen, benötige ich Daten aus der Aktion und auch Daten aus einem Teil des Zustands, der nicht von diesem Reduzierer verwaltet wird. In dem Reduzierer, den ich unten zeigen werde, brauche ich Zugriff auf das accountDetails.stateOfResidenceId-Feld.

initialState.js:

export default {
    accountDetails: {
        stateOfResidenceId: '',
        accountType: '',
        accountNumber: '',
        product: ''
    },
    forms: {
        blueprints: [

        ]
    }
};

formsReducer.js:

import * as types from '../constants/actionTypes';
import objectAssign from 'object-assign';
import initialState from './initialState';
import formsHelper from '../utils/FormsHelper';
export default function formsReducer(state = initialState.forms, action) {
  switch (action.type) {
    case types.UPDATE_PRODUCT: {
        //I NEED accountDetails.stateOfResidenceId HERE
        console.log(state);
        const formBlueprints = formsHelper.getFormsByProductId(action.product.id);
        return objectAssign({}, state, {blueprints: formBlueprints});
    }

    default:
      return state;
  }
}

index.js (Wurzelreduzierer):

import { combineReducers } from 'redux';
import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

const rootReducer = combineReducers({
    accountDetails,
    forms
});

export default rootReducer;

Wie kann ich auf dieses Feld zugreifen?

50
twilco

Ich würde thunk dafür verwenden, hier ein Beispiel:

export function updateProduct(product) {
  return (dispatch, getState) => {
    const { accountDetails } = getState();

    dispatch({
      type: UPDATE_PRODUCT,
      stateOfResidenceId: accountDetails.stateOfResidenceId,
      product,
    });
  };
}

Grundsätzlich erhalten Sie alle Daten, die Sie für die Aktion benötigen, und können diese Daten an Ihren Reducer senden.

70
Crysfel

Sie haben die Möglichkeit, neben der Verwendung von combineReducers mehr Logik zu schreiben oder mehr Daten in die Aktion aufzunehmen. Die Redux FAQ behandelt dieses Thema: http://redux.js.org/docs/faq/Reducers.html#reducers-share-state .

Außerdem arbeite ich derzeit an neuen Seiten zu den Redux-Dokumenten zum Thema "Strukturierung von Reduzierstücken", die möglicherweise hilfreich sind. Die aktuellen WIP-Seiten finden Sie unter https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md .

8
markerikson

Eine alternative Möglichkeit, wenn Sie React-Redux verwenden und diese Aktion nur an einer Stelle benötigen OR, ist das Erstellen eines HOC (Higher oder component) in Ordnung ) überall, wo Zugriff benötigt wird, ist mergeprops zu verwenden, wobei die zusätzlichen Parameter an die Aktion übergeben werden:

const mapState = ({accountDetails: {stateOfResidenceId}}) => stateOfResidenceId;

const mapDispatch = (dispatch) => ({
  pureUpdateProduct: (stateOfResidenceId) => dispatch({ type: types.UPDATE_PRODUCT, payload: stateOfResidenceId })
});

const mergeProps = (stateOfResidenceId, { pureUpdateProduct}) => ({hydratedUpdateProduct: () => pureUpdateProduct(stateOfResidenceId )});

const addHydratedUpdateProduct = connect(mapState, mapDispatch, mergeProps)

export default addHydratedUpdateProduct(ReactComponent);

export const OtherHydratedComponent = addHydratedUpdateProduct(OtherComponent)

Wenn Sie mergeProps verwenden, wird das, was Sie zurückgeben, zu den Requisiten hinzugefügt. MapState und mapDispatch dienen nur dazu, die Argumente für mergeProps bereitzustellen. Mit anderen Worten, diese Funktion fügt dies Ihren Komponenten-Requisiten hinzu (TypeScript-Syntax):

{hydratedUpdateProduct: () => void}

(Beachten Sie, dass die Funktion die Aktion selbst zurückgibt und nicht ungültig ist, dies wird jedoch in den meisten Fällen ignoriert.).

Aber was Sie tun können, ist:

const mapState = ({ accountDetails }) => accountDetails;

const mapDispatch = (dispatch) => ({
  pureUpdateProduct: (stateOfResidenceId) => dispatch({ type: types.UPDATE_PRODUCT, payload: stateOfResidenceId })
  otherAction: (param) => dispatch(otherAction(param))
});

const mergeProps = ({ stateOfResidenceId, ...passAlong }, { pureUpdateProduct, ... otherActions}) => ({
  ...passAlong,
  ...otherActions,
  hydratedUpdateProduct: () => pureUpdateProduct(stateOfResidenceId ),
});

const reduxPropsIncludingHydratedAction= connect(mapState, mapDispatch, mergeProps)

export default reduxPropsIncludingHydratedAction(ReactComponent);

dadurch erhalten die Requisiten die folgenden Informationen:

{
  hydratedUpdateProduct: () => void,
  otherAction: (param) => void,
  accountType: string,
  accountNumber: string,
  product: string,
}

Im Großen und Ganzen ist die völlige Ablehnung der Redux-Betreuer, die Funktionalität ihres Pakets zu erweitern, um solche Wünsche auf eine gute Weise einzubeziehen, die ein Muster für diese Funktionalitäten schaffen würde, OHNE eine Fragmentierung des Ökosystems zu unterstützen, beeindruckend.

Pakete wie Vuex, die nicht so hartnäckig sind, haben nicht annähernd so viele Probleme mit Menschen, die Antimuster missbrauchen, weil sie verloren gehen, und unterstützen gleichzeitig eine sauberere Syntax mit weniger Boilerplate als jemals zuvor mit Redux und den besten unterstützenden Paketen. Und obwohl das Paket viel vielseitiger ist, ist die Dokumentation einfacher zu verstehen, da sie nicht in den Details verloren geht, wie es die Redux-Dokumentation normalerweise tut.

0
Sam96

Ich vermute, dass Sie es an den Action-Ersteller übergeben. So irgendwo hast du einen Action Creator, der so etwas macht: 

updateProduct(arg1, arg2, stateOfResidenceId) {
  return {
    type: UPDATE_PRODUCT,
    stateOfResidenceId
  }
}

An der Stelle, an der Sie die Aktion auslösen, können Sie davon ausgehen, dass Sie reagieren 

function mapStateToProps(state, ownProps) {
  return {
    stateOfResidenceId: state.accountdetails.stateOfResidenceId
  }  
}

und stellen Sie eine Verbindung zu Ihrer Reakt-Komponente her, indem Sie die Verbindung von React-Redux herstellen. 

connect(mapStateToProps)(YourReactComponent);

Nun sollten Sie in Ihrer Reaktionskomponente, in der Sie die Aktion updateProduct auslösen, die stateOfResidenceId als Requisite haben, die Sie an Ihren Aktionsersteller übergeben können. 

Es klingt kompliziert, aber es geht wirklich um die Trennung von Bedenken. 

0
Xing Wang

Sie können versuchen zu verwenden:

redux-named-reduucers

Dadurch können Sie den Code an beliebiger Stelle in Ihrem Code abrufen:

const localState1 = getState(reducerA.state1)
const localState2 = getState(reducerB.state2)

Aber denken Sie zuerst darüber nach, ob es besser wäre, den Außenstaat als Nutzlast in der Aktion zu übergeben. 

0
miles_christian

Ich bin nicht sicher, ob dieser Ansatz ein Anti-Muster ist, aber es hat für mich funktioniert. Verwenden Sie eine Curry-Funktion in Ihren Aktionen.

export const myAction = (actionData) => (dispatch, getState) => {
   dispatch({
      type: 'SOME_ACTION_TYPE',
      data: actionData,
      state: getState()
   });
}
0
user3377090

Es ist einfach, eine eigene Kombinationsfunktion zu schreiben, die genau das tut, was Sie wollen:

import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

const rootReducer = (state, action) => {
        const newState = {};

        newState.accountDetails = accountDetails(state.accountDetails, action);
        newState.forms = forms(state.forms, action, state.accountDetails);

        return newState;
    };

export default rootReducer; 

Ihr FormReducer wäre dann:

export default function formsReducer(state = initialState.forms, action, accountDetails) {

Der formsReducer hat nun Zugriff auf die accountDetails.

Der Vorteil dieses Ansatzes besteht darin, dass Sie anstelle des gesamten Zustands nur die benötigten Zustandsscheiben anzeigen.

0
GhostEcho