반응 구성 요소 외부에서 Redux Store에 액세스하는 가장 좋은 방법은 무엇입니까?
@connect
반응 구성 요소 내 상점에 액세스하려고 할 때 효과적입니다. 그러나 다른 코드로 어떻게 액세스해야합니까? 예를 들어, 내 앱에서 전 세계적으로 사용할 수있는 axios 인스턴스를 생성하기 위해 인증 토큰을 사용하려고한다고 가정 해 봅시다.이를 달성하는 가장 좋은 방법은 무엇입니까?
이것은 나의 api.js
// tooling modules
import axios from 'axios'
// configuration
const api = axios.create()
api.defaults.baseURL = 'http://localhost:5001/api/v1'
api.defaults.headers.common['Authorization'] = 'AUTH_TOKEN' // need the token here
api.defaults.headers.post['Content-Type'] = 'application/json'
export default api
이제 내 상점에서 데이터 포인트에 액세스하고 싶습니다. 여기를 사용하여 반응 구성 요소 내에서 데이터 포인트를 가져 오려고하면 어떻게 보일까요? @connect
// connect to store
@connect((store) => {
return {
auth: store.auth
}
})
export default class App extends Component {
componentWillMount() {
// this is how I would get it in my react component
console.log(this.props.auth.tokens.authorization_token)
}
render() {...}
}
통찰력이나 워크 플로 패턴이 있습니까?
호출 한 모듈에서 상점을 내보내십시오 createStore
. 그런 다음 전역 창 공간을 만들거나 오염시키지 않을 것입니다.
MyStore.js
const store = createStore(myReducer);
export store;
또는
const store = createStore(myReducer);
export default store;
MyClient.js
import {store} from './MyStore'
store.dispatch(...)
또는 기본값 을 사용한 경우
import store from './MyStore'
store.dispatch(...)
여러 상점 사용 사례
상점의 여러 인스턴스가 필요한 경우 팩토리 기능을 내보내십시오. 그것을 만드는 것이 좋습니다 async
(을 반환 promise
).
async function getUserStore (userId) {
// check if user store exists and return or create it.
}
export getUserStore
클라이언트에서 ( async
블록 내)
import {getUserStore} from './store'
const joeStore = await getUserStore('joe')
해결책을 찾았습니다. 그래서 내 API 유틸리티에서 상점을 가져 와서 구독하십시오. 그리고 그 리스너 기능에서 새로 가져온 토큰으로 axios의 전역 기본값을 설정했습니다.
이것이 나의 새로운 api.js
모습입니다 :
// tooling modules
import axios from 'axios'
// store
import store from '../store'
store.subscribe(listener)
function select(state) {
return state.auth.tokens.authentication_token
}
function listener() {
let token = select(store.getState())
axios.defaults.headers.common['Authorization'] = token;
}
// configuration
const api = axios.create({
baseURL: 'http://localhost:5001/api/v1',
headers: {
'Content-Type': 'application/json',
}
})
export default api
어쩌면 그것은 조금 더 개선 될 수 있습니다. 나중에 할 수있는 일은 미들웨어를 내 상점에 추가하고 토큰을 설정하는 것입니다.
You can use store
object that is returned from createStore
function (which should be already used in your code in app initialization). Than you can use this object to get current state with store.getState()
method or store.subscribe(listener)
to subscribe to store updates.
You can even save this object to window
property to access it from any part of application if you really want it (window.store = store
)
More info can be found in the Redux documentation .
Seems like Middleware
is the way to go.
Refer the official documentation and this issue on their repo
Like @sanchit proposed middleware is a nice solution if you are already defining your axios instance globally.
You can create a middleware like:
function createAxiosAuthMiddleware() {
return ({ getState }) => next => (action) => {
const { token } = getState().authentication;
global.axios.defaults.headers.common.Authorization = token ? `Bearer ${token}` : null;
return next(action);
};
}
const axiosAuth = createAxiosAuthMiddleware();
export default axiosAuth;
And use it like this:
import { createStore, applyMiddleware } from 'redux';
const store = createStore(reducer, applyMiddleware(axiosAuth))
It will set the token on every action but you could only listen for actions that change the token for example.
For TypeScript 2.0 it would look like this:
MyStore.ts
export namespace Store {
export type Login = { isLoggedIn: boolean }
export type All = {
login: Login
}
}
import { reducers } from '../Reducers'
import * as Redux from 'redux'
const reduxStore: Redux.Store<Store.All> = Redux.createStore(reducers)
export default reduxStore;
MyClient.tsx
import reduxStore from "../Store";
{reduxStore.dispatch(...)}
An easy way to have access to the token, is to put the token in the LocalStorage or the AsyncStorage with React Native.
Below an example with a React Native project
authReducer.js
import { AsyncStorage } from 'react-native';
...
const auth = (state = initialState, action) => {
switch (action.type) {
case SUCCESS_LOGIN:
AsyncStorage.setItem('token', action.payload.token);
return {
...state,
...action.payload,
};
case REQUEST_LOGOUT:
AsyncStorage.removeItem('token');
return {};
default:
return state;
}
};
...
and api.js
import axios from 'axios';
import { AsyncStorage } from 'react-native';
const defaultHeaders = {
'Content-Type': 'application/json',
};
const config = {
...
};
const request = axios.create(config);
const protectedRequest = options => {
return AsyncStorage.getItem('token').then(token => {
if (token) {
return request({
headers: {
...defaultHeaders,
Authorization: `Bearer ${token}`,
},
...options,
});
}
return new Error('NO_TOKEN_SET');
});
};
export { request, protectedRequest };
For web you can use Window.localStorage
instead of AsyncStorage
'Programming' 카테고리의 다른 글
node.js 대 ASP.NET Core 성능 테스트의 예기치 않은 결과 (0) | 2020.06.03 |
---|---|
디버거는 어떻게 작동합니까? (0) | 2020.06.03 |
'for'루프에서 마지막 요소를 감지하는 pythonic 방법은 무엇입니까? (0) | 2020.06.03 |
HAXM으로 OS X v10.9 (Mavericks)를 고정하는 Android 에뮬레이터 (0) | 2020.06.03 |
C # .NET에서 App.config는 무엇입니까? (0) | 2020.06.03 |