Redux redüktör içindeki duruma nasıl erişilir?


88

Bir indirgeyicim var ve yeni durumu hesaplamak için eylemden verilere ve ayrıca devletin bu indirgeyici tarafından yönetilmeyen bir bölümünden verilere ihtiyacım var. Özellikle aşağıda göstereceğim redüktörde accountDetails.stateOfResidenceIdsahaya girmem gerekiyor .

initialState.js:

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

        ]
    }
};

formlarReducer.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 (kök azaltıcı):

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

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

export default rootReducer;

Bu alana nasıl ulaşabilirim?



8
Bu ifade hiç mantıklı değil. İndirgeyici işlevin tüm amacı, mevcut duruma ve eyleme göre kararlar almanızdır.
markerikson

Yanıtlar:


105

Bunun için thunk kullanırdım , işte bir örnek:

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

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

Temel olarak işlem sırasında ihtiyacınız olan tüm verileri alırsınız, ardından bu verileri düşürücünüze gönderebilirsiniz.


4
REDUX tarafından redüktöre neden mevcut durumun maruz kalmadığı hakkında bir fikriniz var mı ..? Tuhaf görünüyor ki, sevkıyat sırasında indirgeyiciye alakasız şeyler eklemem gerekiyor, böylece başlangıç ​​durumu mevcut gönderim çağrısıyla diğer ilgisiz şeylerin mevcut durumunu geçersiz kılmaz
vsync

10

Seçenekleriniz, sadece kullanımın yanı sıra daha fazla mantık yazmak combineReducersveya eyleme daha fazla veri dahil etmektir. Redux SSS bu konuyu kapsar:

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

Ayrıca, şu anda Redux belgelerinde "Redüktörlerin Yapılandırılması" konusunda faydalı bulabileceğiniz yeni bir sayfa grubu üzerinde çalışıyorum. Mevcut Devam Eden Çalışma sayfaları https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StructuringReducers.md adresindedir .


Cevabınız için teşekkürler. Bağladığınız bazı kaynakları araştırdım ve yapmaya devam edeceğim. Ancak, bilgili göründüğünüz için sizin için bir soru. Başka bir cevap kullanılmasını önerdi thunk. Bunun benim sorunum için iyi bir çözüm olacağını düşünüyor musunuz? Kodumu karıştıracaksa veya en iyi uygulama değilse, takip etmek istediğim bir çözüm değil, ancak bu seçimlerin uzun vadeli etkilerini belirleyecek kadar bilgili hissetmiyorum.
kibowki

3
Evet, thunks, yan etkileri yönetmeye ve birden fazla gönderimi içeren ve mevcut uygulama durumunu kullanan karmaşık mantığı yürütmeye yönelik standart temel yaklaşımdır. Mevcut uygulama durumunu okuyan ve koşullu olarak gönderme, birden fazla eylem gönderme veya durumun bir bölümünü kapma ve bunu gönderilen eylemde içeren bir thunk işlevi yazmak tamamen normaldir. Gist.github.com/markerikson/ea4d0a6ce56ee479fe8b356e099f857e adresinde bazı yaygın thunk modellerine sahibim .
markerikson

2

Bu yaklaşımın bir anti-model olup olmadığından emin değilim ama benim için çalıştı. Eylemlerinizde kıvrımlı bir işlev kullanın.

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

1

Tam olarak istediğinizi yapan kendi birleştirme işlevinizi yazmak çok kolaydır:

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'ınız şu şekilde olacaktır:

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

FormsReducer artık accountDetails'e erişebilir.

Bu yaklaşımın yararı, tüm devlet yerine yalnızca ihtiyacınız olan durum dilimlerini ortaya çıkarmanızdır.


0

Bunu aksiyon yaratıcısına aktarmanızı öneririm. Yani bir yerde şuna benzer bir eylem yaratıcısı olacak:

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

Eylemi tetiklediğiniz yerde, react kullandığınızı varsayın, kullanabilirsiniz

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

ve react-redux'un bağlantısını kullanarak react bileşeninize bağlanın.

connect(mapStateToProps)(YourReactComponent);

Şimdi, updateProduct eylemini tetiklediğiniz react bileşeninizde, bir destek olarak stateOfResidenceId'ye sahip olmalısınız ve bunu eylem oluşturucunuza iletebilirsiniz.

Karmaşık görünüyor, ama gerçekten endişelerin ayrılmasıyla ilgili.


0

Kullanmayı deneyebilirsiniz:

redux adlı redüktörler

Bu, kodunuzun herhangi bir yerinde durumu şu şekilde almanızı sağlar:

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

Ama önce dış durumu eylemde bir yük olarak geçirmenin daha iyi olup olmadığını düşünün.


0

Alternatif bir yol, react-redux kullanıyorsanız ve bu eyleme yalnızca tek bir yerde ihtiyaç duyuyorsanız VEYA bir HOC (Daha yüksek bileşen, gerçekten önemli olanın html'nizi şişirebileceğini anlamanıza gerek yok) ihtiyacınız olan her yerde bu erişim, eyleme geçirilen ek parametrelerle mergeprops kullanmaktır :

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)

MergeProps'u kullandığınızda, geri döndüğünüz şey props'a eklenir, mapState ve mapDispatch yalnızca mergeProps için argümanlar sağlamak için hizmet eder. Yani, başka bir deyişle, bu işlev bunu bileşen props'larınıza (typcript sözdizimi) ekleyecektir:

{hydratedUpdateProduct: () => void}

(işlevin aslında eylemin kendisini döndürdüğünü ve void olmadığını unutmayın, ancak çoğu durumda bunu göz ardı edeceksiniz).

Ama yapabilecekleriniz:

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

bu, sahne elemanlarına aşağıdaki şeyleri sağlayacaktır:

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

Genel olarak, redux bakımcıları, paketlerinin işlevselliğini, bu tür istekleri iyi bir şekilde kapsayacak şekilde genişletmekle birlikte, ekosistemin parçalanmasını desteklemek OLMADAN bu işlevler için bir model oluşturacağını gösterdiler.

Vuex gibi çok inatçı olmayan paketler, anti-modelleri kötüye kullanan insanlarla neredeyse o kadar çok sorun yaşamazlar çünkü kaybolurlar, aynı zamanda redux ve en iyi destekleyici paketlerle arşivleyeceğinizden daha az düz yazı ile çok daha temiz bir sözdizimi destekler. Ve paketin çok daha çok yönlü olmasına rağmen, dokümantasyonun anlaşılması daha kolaydır, çünkü redux dokümantasyonunun yapma eğiliminde olduğu gibi detaylarda kaybolmazlar.


-1

Bir eylem gönderirken bir parametre iletebilirsiniz. Bu durumda, accountDetails.stateOfResidenceIdeyleme geçebilir ve ardından onu yük olarak redüktöre iletebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.