Posiadam reduktor i do wyliczenia nowego stanu potrzebuję danych z akcji oraz danych z części stanu nie zarządzanej przez ten reduktor. Konkretnie w reduktorze pokażę poniżej potrzebuję dostępu do accountDetails.stateOfResidenceId
pola.
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 (reduktor root):
import { combineReducers } from 'redux';
import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';
const rootReducer = combineReducers({
accountDetails,
forms
});
export default rootReducer;
Jak mogę uzyskać dostęp do tego pola?
javascript
reactjs
redux
twilco
źródło
źródło
Odpowiedzi:
Użyłbym thunk o tym, oto przykład:
export function updateProduct(product) { return (dispatch, getState) => { const { accountDetails } = getState(); dispatch({ type: UPDATE_PRODUCT, stateOfResidenceId: accountDetails.stateOfResidenceId, product, }); }; }
Zasadniczo otrzymujesz wszystkie potrzebne dane dotyczące akcji, a następnie możesz wysłać te dane do reduktora.
źródło
Masz do wyboru napisanie większej ilości logiki poza zwykłym użyciem
combineReducers
lub włączenie większej ilości danych do akcji. FAQ Redux obejmuje ten temat:https://redux.js.org/faq/reducers/
Obecnie pracuję również nad nowym zestawem stron do dokumentacji Redux na temat „Strukturyzujących Reduktorów”, które mogą okazać się pomocne. Aktualne strony WIP znajdują się pod adresem https://github.com/markerikson/redux/blob/structuring-reducers-page/docs/recipes/StruifyingReducers.md .
źródło
thunk
. Czy uważasz, że byłoby to dobre rozwiązanie mojego problemu? Jeśli ma narobić bałaganu w moim kodzie lub nie jest najlepszą praktyką, nie jest to rozwiązanie, do którego chciałbym dążyć, ale nie czuję się wystarczająco kompetentny, aby określić długoterminowe skutki tych wyborów.Nie jestem pewien, czy to podejście jest anty-wzorcem, ale zadziałało w moim przypadku. Używaj funkcji curry w swoich działaniach.
export const myAction = (actionData) => (dispatch, getState) => { dispatch({ type: 'SOME_ACTION_TYPE', data: actionData, state: getState() }); }
źródło
Łatwo jest napisać własną funkcję łączenia, która robi dokładnie to, co chcesz:
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;
Twój FormReducer miałby wtedy postać:
export default function formsReducer(state = initialState.forms, action, accountDetails) {
FormsReducer ma teraz dostęp do accountDetails.
Zaletą tego podejścia jest to, że eksponujesz tylko fragmenty stanu, których potrzebujesz, zamiast całego stanu.
źródło
Sugeruję, abyś przekazał to kreatorowi akcji. Więc gdzieś będziesz mieć kreatora akcji, który robi coś takiego:
updateProduct(arg1, arg2, stateOfResidenceId) { return { type: UPDATE_PRODUCT, stateOfResidenceId } }
W miejscu, w którym wyzwalasz akcję, załóż, że używasz Reaguj, możesz użyć
function mapStateToProps(state, ownProps) { return { stateOfResidenceId: state.accountdetails.stateOfResidenceId } }
i połącz się ze swoim komponentem Reaguj za pomocą połączenia React-Redux.
Teraz w komponencie reagowania, w którym uruchamiasz akcję updateProduct, powinieneś mieć atrybut stateOfResidenceId i możesz przekazać go do swojego kreatora akcji.
Brzmi zagmatwane, ale tak naprawdę chodzi o oddzielenie obaw.
źródło
Możesz spróbować użyć:
reduktory o nazwie redux
Co pozwala uzyskać stan w dowolnym miejscu w kodzie, na przykład:
const localState1 = getState(reducerA.state1) const localState2 = getState(reducerB.state2)
Ale zastanów się najpierw, czy lepiej byłoby przekazać stan zewnętrzny jako ładunek w akcji.
źródło
Alternatywny sposób, jeśli używasz React-Redux i potrzebujesz tego działania tylko w jednym miejscu LUB możesz stworzyć HOC (komponent o wyższej jakości, naprawdę nie musisz rozumieć, że ważne jest to, że może to nadmuchać twój HTML) wszędzie, gdzie potrzebujesz dostęp polega na użyciu mergeprops z dodatkowymi parametrami przekazywanymi do akcji:
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)
Kiedy używasz mergeProps, to, co zwrócisz, zostanie dodane do właściwości, mapState i mapDispatch posłużą tylko jako argumenty dla mergeProps. Innymi słowy, ta funkcja doda to do twoich właściwości komponentu (składnia maszynopisu):
{hydratedUpdateProduct: () => void}
(zwróć uwagę, że funkcja w rzeczywistości zwraca samą akcję, a nie void, ale w większości przypadków zignorujesz to).
Ale możesz zrobić:
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);
to dostarczy następujące rzeczy do rekwizytów:
{ hydratedUpdateProduct: () => void, otherAction: (param) => void, accountType: string, accountNumber: string, product: string, }
Ogólnie rzecz biorąc, chociaż całkowite zaniedbanie, które opiekunowie redux wykazują, aby rozszerzyć funkcjonalność swojego pakietu tak, aby zawierał takie życzenia w dobry sposób, który stworzyłby wzorzec dla tych funkcji BEZ wspierania fragmentacji ekosystemu, robi wrażenie.
Pakiety takie jak Vuex, które nie są tak uparte, nie mają prawie tak wielu problemów z ludźmi nadużywającymi antywzorców, ponieważ gubią się, jednocześnie wspierając czystszą składnię z mniejszą liczbą szablonów niż kiedykolwiek archiwizujesz za pomocą Redux i najlepszych pakietów pomocniczych. I pomimo tego, że pakiet jest znacznie bardziej wszechstronny, dokumentacja jest łatwiejsza do zrozumienia, ponieważ nie gubi się w szczegółach, takich jak dokumentacja Redux.
źródło
Wysyłając akcję, możesz przekazać parametr. W takim przypadku możesz przejść
accountDetails.stateOfResidenceId
do akcji, a następnie przekazać ją do reduktora jako ładunek.źródło