Redux reducer के अंदर कैसे पहुंचें?


86

मेरे पास एक reducer है, और नए राज्य की गणना करने के लिए मुझे कार्रवाई से डेटा की आवश्यकता है और इस reducer द्वारा प्रबंधित नहीं किए गए राज्य के एक हिस्से से डेटा भी। विशेष रूप से, reducer में मैं नीचे दिखाऊंगा, मुझे accountDetails.stateOfResidenceIdक्षेत्र तक पहुंच की आवश्यकता है ।

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 (रूट रिड्यूसर):

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

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

export default rootReducer;

मैं इस क्षेत्र तक कैसे पहुँच सकता हूँ?



8
उस बयान का कोई मतलब नहीं है। Reducer फ़ंक्शन का पूरा बिंदु यह है कि आप वर्तमान स्थिति और क्रिया के आधार पर निर्णय लेते हैं ।
ऑक्टिकसन

जवाबों:


105

मैं इसके लिए थंक का उपयोग करूँगा , यहाँ एक उदाहरण है:

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

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

मूल रूप से आपको कार्रवाई पर आवश्यक सभी डेटा मिलते हैं, फिर आप उस डेटा को अपने रिड्यूसर को भेज सकते हैं।


4
किसी भी विचार क्यों REDUX द्वारा वर्तमान स्थिति reducer के संपर्क में नहीं है ..? यह अजीब लगता है कि जब डिस्पैच करने के लिए मुझे रिड्यूसर में अप्रासंगिक चीजों को जोड़ने की आवश्यकता होती है, तो प्रारंभिक स्थिति वर्तमान डिस्पैच कॉल के लिए अन्य असंबंधित सामान की वर्तमान स्थिति को ओवरराइड नहीं करेगी
vsync

10

आपके विकल्प केवल या तो उपयोग के अलावा और अधिक तर्क लिखना है combineReducers, या कार्रवाई में अधिक डेटा शामिल करना है। Redux FAQ में इस विषय को शामिल किया गया है:

https://redux.js.org/faq/reducers/

इसके अलावा, मैं वर्तमान में "संरचित Reducers" के विषय पर Redux डॉक्स के लिए पृष्ठों के एक नए सेट पर काम कर रहा हूं, जो आपको मददगार लग सकता है। वर्तमान WIP पृष्ठ https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md पर हैं


आपके उत्तर के लिए धन्यवाद। मैंने आपके द्वारा लिंक किए गए कुछ संसाधनों का पता लगाया है, और ऐसा करना जारी रखेगा। हालाँकि, आपके लिए प्रश्न, चूंकि आप जानकार लगते हैं। एक अन्य जवाब के उपयोग का सुझाव दिया thunk। क्या आपको लगता है कि यह मेरी समस्या का अच्छा समाधान होगा? यदि यह मेरे कोड की गड़बड़ी करने जा रहा है या यह एक सर्वोत्तम अभ्यास नहीं है, तो इसका कोई हल नहीं है जिसे मैं आगे बढ़ाना चाहता हूं, लेकिन मैं इन विकल्पों के दीर्घकालिक प्रभावों को निर्धारित करने के लिए पर्याप्त जानकार नहीं हूं।
ट्विलाको

3
यूप, थ्रक्स साइड इफेक्ट्स के प्रबंधन और जटिल तर्क को निष्पादित करने के लिए मानक बुनियादी दृष्टिकोण है जिसमें कई प्रेषण शामिल हैं और वर्तमान ऐप राज्य का उपयोग कर रहे हैं। एक थंक फ़ंक्शन लिखना पूरी तरह से सामान्य है जो वर्तमान एप्लिकेशन स्थिति को पढ़ता है, और सशर्त रूप से प्रेषण, कई क्रियाओं को प्रेषण, या राज्य के कुछ हिस्सों को भेजता है और इसमें एक प्रेषण कार्रवाई शामिल है। मेरे पास gist.github.com/markerikson/ea4d0a6ce56ee479fe8b356e099f857e पर सामान्य थंक पैटर्न के कुछ उदाहरण हैं ।
मार्करसन

2

मुझे यकीन नहीं है कि यह दृष्टिकोण एक विरोधी पैटर्न है लेकिन यह मेरे लिए काम करता है। अपने कार्यों में एक करी फ़ंक्शन का उपयोग करें।

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

1

अपने स्वयं के संयोजन फ़ंक्शन को लिखना आसान है जो वास्तव में आप चाहते हैं:

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; 

आपका FormReducer तब होगा:

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

फ़ॉर्मरेडर के पास अब अकाउंटडेल्स तक पहुंच है।

इस दृष्टिकोण का लाभ यह है कि आप केवल पूरे राज्य के बजाय राज्य के स्लाइस को अपनी आवश्यकता के अनुसार उजागर करते हैं।


0

मैं यह मानता हूं कि आप इसे एक्शन क्रिएटर के रूप में देखते हैं। तो कहीं न कहीं आपके पास एक एक्शन क्रिएटर होगा जो कुछ ऐसा करता है:

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

उस स्थान पर जहां आप कार्रवाई को ट्रिगर करते हैं, मान लें कि आप प्रतिक्रिया का उपयोग कर रहे हैं, आप उपयोग कर सकते हैं

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

और प्रतिक्रिया-रिड्यूक्स कनेक्ट का उपयोग करके अपने प्रतिक्रिया घटक से कनेक्ट करें।

connect(mapStateToProps)(YourReactComponent);

अब, आपके प्रतिक्रिया घटक में जहां आप क्रिया अद्यतन को ट्रिगर करते हैं, आपके पास प्रॉप के रूप में StateOfResidenceId होना चाहिए, और आप इसे अपने एक्शन निर्माता को पास कर सकते हैं।

यह जटिल लगता है, लेकिन यह वास्तव में चिंताओं को अलग करने के बारे में है।


0

आप उपयोग करने की कोशिश कर सकते हैं:

Redux नाम-reducers

जिससे आप अपने कोड में कहीं भी राज्य प्राप्त कर सकते हैं:

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

लेकिन पहले सोचें कि क्या बाहरी राज्य को कार्रवाई में पेलोड के रूप में पारित करना बेहतर होगा।


0

एक वैकल्पिक तरीका है, यदि आप प्रतिक्रिया-रिडक्स का उपयोग करते हैं और केवल एक ही स्थान पर उस क्रिया की आवश्यकता होती है या एचओसी (उच्चतर घटक) बनाने के साथ ठीक है, तो वास्तव में यह समझने की आवश्यकता नहीं है कि महत्वपूर्ण सामान यह है कि यह आपके html को ब्लोट कर सकता है) हर जगह आपकी ज़रूरत है उस पहुंच का उपयोग मर्जप्रॉप्स का उपयोग करना है जो अतिरिक्त मापदंडों के साथ कार्रवाई के लिए पारित किया जा रहा है:

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)

जब आप मर्जप्रॉप्स का उपयोग करते हैं, तो आप जो लौटाते हैं, वह प्रॉपर में जोड़ा जाएगा, मैपस्टैट और मैपडाइस्पैच केवल मर्जप्रॉप्स के लिए तर्क प्रदान करने के लिए काम करेंगे। तो, दूसरे शब्दों में, यह फ़ंक्शन इसे आपके घटक प्रॉपर (टाइपस्क्रिप्ट सिंटैक्स) में जोड़ देगा:

{hydratedUpdateProduct: () => void}

(ध्यान रखें कि फ़ंक्शन वास्तव में क्रिया को स्वयं लौटाता है और शून्य नहीं है, लेकिन आप ज्यादातर मामलों में इसे अनदेखा करेंगे)।

लेकिन आप क्या कर सकते हैं:

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);

यह सहारा के लिए निम्नलिखित सामान प्रदान करेगा:

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

पूरी तरह से हालांकि पूरी तरह से असंतुलन redux-maintainers उनके पैकेज की कार्यक्षमता का विस्तार करने के लिए इस तरह की इच्छाओं को अच्छे तरीके से शामिल करने के लिए दिखाता है, जो पारिस्थितिकी तंत्र के विखंडन का समर्थन किए बिना इन कार्यक्षमताओं के लिए एक पैटर्न बनाएगा, प्रभावशाली है।

Vuex जैसे पैकेज जो इतने ज़िद्दी नहीं हैं, एंटीपार्टर्न को गाली देने वाले लोगों के साथ लगभग इतने सारे मुद्दे नहीं हैं क्योंकि वे खो जाते हैं, जबकि कम बॉयलर के साथ एक तरह से क्लीनर सिंटैक्स का समर्थन करने की तुलना में आप कभी भी रिडक्स और सर्वश्रेष्ठ सहायक पैकेज के साथ संग्रह करेंगे। और पैकेज अधिक बहुमुखी होने के बावजूद डोक्यूमेन्टेशन को समझना आसान है, क्योंकि वे विवरण में खो नहीं जाते हैं जैसे कि रेड्यूक्स प्रलेखन को जाता है।


-1

किसी कार्रवाई को भेजते समय, आप एक पैरामीटर पास कर सकते हैं। इस मामले में, आप accountDetails.stateOfResidenceIdकार्रवाई को पारित कर सकते हैं और फिर इसे पेलोडर के रूप में रिड्यूसर पर पास कर सकते हैं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.