web-dev-qa-db-fra.com

L'utilisation de getState dans une Redux Thunk est-elle une bonne pratique?

J'ai vu des réponses contradictoires (ou tout simplement déroutantes pour moi) dans d'autres questions ici concernant si l'utilisation de getState dans une action est acceptable ou non, et j'ai vu à plusieurs reprises que cela était appelé un anti-modèle . Pour moi, cela semble fonctionner très bien, mais quelle est la meilleure pratique pour le faire si nous ne devons pas utiliser getState?

J'utilise getState dans un thunk pour filtrer à travers un tableau d'utilisateurs qui est actuellement connecté à certaines données fictives et qui est tiré dans l'état de l'application.

Voici le code de mon action:

export const accountLogInSuccess = user => ({
    type: types.ACCOUNT_LOG_IN_SUCCESS,
    user,
});

export const accountLogOutSuccess = () => ({
    type: types.ACCOUNT_LOG_OUT_SUCCESS,
});

export const accountCheckSuccess = () => ({
    type: types.ACCOUNT_CHECK_SUCCESS,
});

export const accountCheck = () => (
    (dispatch, getState) => {
        dispatch(ajaxCallBegin());
        return apiAccount.accountCheck().then((account) => {
            if (account) {
                const user = findByUID(getState().users, account.uid);
                dispatch(accountLogInSuccess(user));
                toastr.success(`Welcome ${user.nameFirst}!`);
            } else {
                dispatch(accountLogOutSuccess());
            }
            dispatch(accountCheckSuccess());
        }).catch((error) => {
            dispatch(ajaxCallError(error));
            toastr.error(error.message);
            throw (error);
        });
    }
);

Et mon réducteur:

export default function reducerAccount(state = initial.account, action) {
    switch (action.type) {
    case types.ACCOUNT_LOG_IN_SUCCESS:
        return Object.assign({}, state, action.user, {
            authenticated: true,
        });
    case types.ACCOUNT_LOG_OUT_SUCCESS:
        return Object.assign({}, {
            authenticated: false,
        });
    case types.ACCOUNT_CHECK_SUCCESS:
        return Object.assign({}, state, {
            initialized: true,
        });
    default:
        return state;
    }
}

L'état de compte initial utilisé dans mon réducteur est juste:

account: {
    initialized: false,
    authenticated: false,
},

L'action accountCheck transmet l'utilisateur (trouvé à l'aide de getState et de la fonction findByUID) dans accountLogInSuccess où le réducteur ajoute ses valeurs à l'état actuel du compte via Object.assign.

Préférant ne pas avoir à placer l'utilisateur à la racine de mon application, puis à le transmettre via des accessoires, quelle est la meilleure pratique pour y parvenir au sein de Redux et que les données utilisateur soient disponibles à l'état? Encore une fois, l'utilisation de getState dans le thunk me convient jusqu'à présent, mais y a-t-il une meilleure solution à cela qui n'est pas considérée comme un anti-modèle?

21
spunge

J'ai écrit un article de blog étendu intitulé Idiomatic Redux: Réflexions sur les thunks, les sagas, l'abstraction et la réutilisation , qui aborde ce sujet en détail. Dans ce document, je réponds à plusieurs critiques des thunks et de l'utilisation de getState (y compris les commentaires de Dan Abramov dans Accéder à l'état Redux dans un créateur d'action? ). En fait, mon message a été spécifiquement inspiré par des questions comme la vôtre.

En tant que TL; DR de mon message: je crois que les thunks sont un outil complètement viable pour une utilisation dans les applications Redux et j'encourage leur utilisation. Bien qu'il existe certaines préoccupations valables à prendre en compte lors de l'utilisation de thunks et de sagas, et en utilisant getState/select à l'intérieur d'eux, ces préoccupations ne devraient pas vous effrayer d'utiliser des thunks.

26
markerikson