Dla kodu, który musi się zdarzać wielokrotnie i dla czegoś, co musi być płynne i ogólne, middleware są zwykle drogą do zrobienia. Może to być tak proste, jak dodanie dwóch linii kodu, aby uwzględnić oprogramowanie pośrednie podczas tworzenia sklepu i napisanie prostej funkcji, która zajmie się logiką tokena.
Powiedzmy byś stworzyć swój sklep jako takie:
import { createStore, applyMiddleware, compose } from 'redux';
import rootReducer from './reducers';
import { browserHistory } from 'react-router';
import { routerMiddleware } from 'react-router-redux';
import tokenMiddleware from './middleware/token';
const finalCreateStore = compose(
applyMiddleware(
routerMiddleware(browserHistory),
tokenMiddleware,
),
window.devToolsExtension ? window.devToolsExtension() : f => f,
)(createStore);
Wtedy można by nazwać tę funkcję skądś, z początkowego stanu.
const store = finalCreateStore(rootReducer, initialState);
Pozwoli to zrobić coś ze wszystkimi działaniami, które przechodzą przez sklep. Ponieważ bardzo popularne jest oprogramowanie pośrednie, które obsługuje zgłoszenia API za pomocą obietnic, niektórzy ludzie wolą ponownie je wykorzystać w tym celu i połączyć je razem.
Typowa middleware będzie wyglądać mniej więcej tak:
export const tokenMiddleware = ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') { // pass along
return action(dispatch, getState);
}
// so let's say you have a token that's about to expire
// and you would like to refresh it, let's write so pseudo code
const currentState = getState();
const userObj = state.authentication.user;
if (userObj.token && userObj.token.aboutToExpire) {
const config = getSomeConfigs();
// some date calculation based on expiry time that we set in configs
const now = new Date();
const refreshThreshold = config.token.refreshThreshold;
if (aboutToExpireAndIsBelowThresholdToRefresh) {
// refreshTheToken can be an action creator
// from your auth module for example
// it should probably be a thunk so that you can handle
// an api call and a promise within once you get the new token
next(refreshTheToken(userObj, someOtherParams);
}
}
....
return next(action);
}
Twój token odświeżania thunk może być coś podobnego do tego:
function refreshToken(user, maybeSomeOtherParams) {
const config = getSomeConfigs;
return dispatch => {
makeAPostCallWithParamsThatReturnsPromise
.then(result => dispatch(saveNewToken({
result,
...
})))
.catch(error => dispatch({
type: uh_oh_token_refresh_failed_action_type,
error,
}));
};
Inną alternatywą, które można ewentualnie przejść dla byłoby obsługiwać to przy zmianie trasy.
Załóżmy, że masz gdzieś trasę najwyższego poziomu dla tras, które wymagają uwierzytelnienia, i ważnego użytkownika do obecności w systemie. Nazwijmy je authenticated routes
.
Można zawinąć te authenticated routes
trasą najwyższego poziomu, która definiuje funkcję obsługi funkcji onChange
.Coś takiego:
<Route onChange={authEntry}>
<Route ... /> // authenticated routes
<Route ... />
</Route>
Podczas tworzenia tych tras i utworzenie sklepu, po utworzeniu sklepu, można powiązać go z tej funkcji o nazwie checkAuth
.
const authEntry = checkAuth.bind(null, store)
Innym sposobem byłoby owinąć definicje trasy w funkcji i przekazać sklep do niego, a wtedy masz dostęp tylko samo, ale okazało się, że nie może być tak czyste jak ten (osobistych preferencji).
Co teraz zrobi ten checkAuth
?
coś takiego:
export function checkAuth (store, previous, next, replace, callback) {
const currentUser = store.getState().auth.user
// can possibly dispatch actions from here too
// store.dispatch(..).then(() => callback())..
// so you could possibly refresh the token here using an API call
// if it is about to expire
// you can also check if the token did actually expire and/or
// there's no logged in user trying to access the route, so you can redirect
if (!currentUser || !isLoggedIn(currentUser)) {
replace('/yourLoginRouteHere')
}
callback() // pass it along
}
Obie te powinny być wystarczająco rodzajowy, tak by zapewnić Państwu wielokrotnego użytku kodu w centralnej lokalizacji. Mam nadzieję, że znajdziesz te pomocne.
Mimo, że istnieje odpowiedź oznaczająca rozwiązanie, każdy jest bardzo mile widziany, aby dodać swoje przemyślenia i doświadczenia. –