Ich habe einen Reduzierer, und um den neuen Status zu berechnen, benötige ich Daten aus der Aktion sowie Daten aus einem Teil des Status, der nicht von diesem Reduzierer verwaltet wird. Insbesondere in dem unten gezeigten Reduzierer benötige 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 (Root Reducer):
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?
javascript
reactjs
redux
Kibowki
quelle
quelle
Antworten:
Ich würde dafür Thunk 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 dann an Ihren Reduzierer senden.
quelle
Sie können entweder mehr Logik schreiben als nur verwenden
combineReducers
oder mehr Daten in die Aktion einbeziehen. Die Redux-FAQ behandelt dieses Thema:https://redux.js.org/faq/reducers/
Außerdem arbeite ich derzeit an einer neuen Reihe von Seiten in den Redux-Dokumenten zum Thema "Strukturieren von Reduzierern", die Sie möglicherweise hilfreich finden. Die aktuellen WIP-Seiten finden Sie unter https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md .
quelle
thunk
. Glaubst du, das wäre eine gute Lösung für mein Problem? Wenn es meinen Code durcheinander bringt oder keine bewährte Methode ist, ist es keine Lösung, die ich verfolgen möchte, aber ich fühle mich nicht gut genug informiert, um die langfristigen Auswirkungen dieser Entscheidungen zu bestimmen.Ich bin mir nicht sicher, ob dieser Ansatz ein Anti-Muster ist, aber er hat bei mir funktioniert. Verwenden Sie eine Curry-Funktion in Ihren Aktionen.
export const myAction = (actionData) => (dispatch, getState) => { dispatch({ type: 'SOME_ACTION_TYPE', data: actionData, state: getState() }); }
quelle
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 jetzt Zugriff auf die accountDetails.
Der Vorteil dieses Ansatzes besteht darin, dass Sie statt des gesamten Zustands nur die von Ihnen benötigten Zustandsscheiben verfügbar machen.
quelle
Ich schlage vor, dass Sie es an den Action Creator weitergeben. Irgendwo haben Sie also einen Action Creator, der so etwas macht:
updateProduct(arg1, arg2, stateOfResidenceId) { return { type: UPDATE_PRODUCT, stateOfResidenceId } }
Angenommen, Sie verwenden "Reagieren" an der Stelle, an der Sie die Aktion auslösen
function mapStateToProps(state, ownProps) { return { stateOfResidenceId: state.accountdetails.stateOfResidenceId } }
und verbinden Sie sich mit Ihrer Reaktionskomponente über die Verbindung des React-Redux.
In Ihrer Reaktionskomponente, in der Sie das Aktionsaktualisierungsprodukt auslösen, sollten Sie nun die stateOfResidenceId als Requisite haben und diese an Ihren Aktionsersteller übergeben können.
Es klingt verworren, aber es geht wirklich um die Trennung von Bedenken.
quelle
Sie können versuchen, Folgendes zu verwenden:
Redux-Named-Reducer
So können Sie den Status überall in Ihrem Code wie folgt abrufen:
const localState1 = getState(reducerA.state1) const localState2 = getState(reducerB.state2)
Aber denken Sie zuerst darüber nach, ob es besser wäre, den externen Zustand als Nutzlast in der Aktion zu übergeben.
quelle
Eine alternative Möglichkeit, wenn Sie React-Redux verwenden und diese Aktion nur an einer Stelle benötigen, ODER wenn Sie ein HOC (Higher oder Component, müssen Sie nicht wirklich verstehen, dass das Wichtigste darin besteht, dass dies Ihr HTML aufblähen könnte) überall dort sind, wo Sie es benötigen Bei diesem Zugriff werden Mergeprops verwendet, 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 dort 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 (Typoskript-Syntax):
{hydratedUpdateProduct: () => void}
(Beachten Sie, dass die Funktion die Aktion selbst zurückgibt und nicht ungültig ist. In den meisten Fällen wird dies jedoch 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 Folgendes:
{ hydratedUpdateProduct: () => void, otherAction: (param) => void, accountType: string, accountNumber: string, product: string, }
Insgesamt ist die völlige Ablehnung, die die Redux-Betreuer zeigen, um die Funktionalität ihres Pakets zu erweitern, um solche Wünsche auf eine gute Weise zu berücksichtigen, die ein Muster für diese Funktionen ohne Unterstützung der Fragmentierung des Ökosystems schaffen würde, 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 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 leichter zu verstehen, da sie nicht in den Details verloren geht, wie dies bei der Redux-Dokumentation der Fall ist.
quelle
Während Sie eine Aktion auslösen, können Sie einen Parameter übergeben. In diesem Fall können Sie
accountDetails.stateOfResidenceId
an die Aktion übergeben und sie dann als Nutzlast an den Reduzierer weitergeben.quelle