シームレスで汎用的なものが必要なコードでは、通常はミドルウェアが必要です。ストアを作成する際にミドルウェアを含めるコードと、トークンロジックを処理するシンプルな関数を記述するために、2行のコードを追加するだけで簡単です。
はあなたがのようなお店を作成しましょう:
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);
その後は、初期状態で、どこからこの関数を呼び出します。
const store = finalCreateStore(rootReducer, initialState);
これにより、店舗を通過するすべての操作で何かを行うことができます。約束を使ってAPIコールを処理するミドルウェアを持つことは非常に一般的であるため、この目的のためにAPIコールを再利用して一緒にバンドルすることを好む人もいます。あなたは、おそらくのために行くことができる別の方法で処理することです
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,
}));
};
:あなたのリフレッシュトークンサンクは、これに似たものになる可能性が
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);
}
:
典型的なミドルウェアは、このようになります。これはルートを変更するときです。
認証が必要なルートと有効なユーザーがシステムに存在するルートのどこかにトップレベルのルートがあるとします。それらをauthenticated routes
と呼んでみましょう。
authenticated routes
は、onChange
ハンドラ関数を定義する最上位ルートでラップできます。このような何か:
<Route onChange={authEntry}>
<Route ... /> // authenticated routes
<Route ... />
</Route>
これらのルートを作成し、あなたが店を作成したら、あなたはcheckAuth
と呼ばれるこの機能にバインドすることができ、あなたの店をセットアップします。
const authEntry = checkAuth.bind(null, store)
もう一つの方法は、関数内のルート定義をラップし、その中に店を通過し、その後、あなただけの同じアクセス権を持っているだろうことであろうが、私はそれはのようにきれいではないことが判明し、この(個人的な好みとして)。
今このcheckAuth
は何をしますか?このような
何か:彼らは中央の場所で再利用可能なコードを提供するよう
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
}
これらの両方が十分に汎用的でなければなりません。これらが役立つことを願っています。
解決策が示されているにもかかわらず、誰もが自分の思考や経験を追加することを大変歓迎しています。 –