¿Cuál es la mejor manera de acceder a la tienda redux fuera de un componente de reacción?

@connect funciona muy bien cuando bash acceder a la tienda dentro de un componente de reacción. Pero ¿cómo debería acceder a él en algún otro código? Por ejemplo: digamos que quiero usar un token de autorización para crear mi instancia de axios que se pueda usar globalmente en mi aplicación, ¿cuál sería la mejor manera de lograrlo?

Este es mi 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 

Ahora quiero acceder a un punto de datos de mi tienda, aquí es lo que se vería si estuviera tratando de @connect dentro de un componente de reacción usando @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() {...} } 

¿Alguna información o patrones de flujo de trabajo por ahí?

Exporte la tienda desde el módulo al que llamó createStore. Entonces está seguro de que ambos serán creados y no contaminarán el espacio global de la ventana.

MyStore.js

store = createStore(myReducer); export store;

o

store = createStore(myReducer); export default store;

MyClient.js

import {store} from './MyStore' store.dispatch(...)

o si usaste por defecto

import store from './MyStore' store.dispatch(...)

Encontré una solución. Así que importé la tienda en mi API y me suscribí allí. Y en esa función de oyente fijé los valores predeterminados globales de los axios con el token recién recuperado.

Así es como luce mi nuevo 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 

Tal vez se pueda mejorar aún más, porque actualmente parece un poco poco elegante. Lo que podría hacer después es agregar un middleware a mi tienda y configurar el token en ese momento.

Puede usar el objeto store que se devuelve desde la función createStore (que ya debería estar usada en su código durante la inicialización de la aplicación). Entonces puede usar este objeto para obtener el estado actual con el método store.getState() o store.subscribe(listener) para suscribirse a las actualizaciones de la tienda.

Incluso puede guardar este objeto en la propiedad de window para acceder desde cualquier parte de la aplicación si realmente lo desea ( window.store = store )

Se puede encontrar más información en la documentación de Redux .

Parece que Middleware es el camino a seguir.
Remita la documentación oficial y este problema en su repo

El middleware propuesto por @sanchit es una buena solución si ya está definiendo su instancia de axios globalmente.

Puede crear un middleware como:

 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; 

Y úsalo así:

 import { createStore, applyMiddleware } from 'redux'; const store = createStore(reducer, applyMiddleware(axiosAuth)) 

Configurará el token en cada acción, pero solo podría escuchar las acciones que cambian el token, por ejemplo.

Para TypeScript 2.0 se vería así:

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 = Redux.createStore(reducers) export default reduxStore; 

MyClient.tsx

 import reduxStore from "../Store"; {reduxStore.dispatch(...)} 

Esta pregunta es bastante antigua, pero creo que vale la pena compartir mi idea.

En lugar de almacenar el token en la tienda redux, lo guardo en la memoria.
* Cuando se carga la aplicación, lee TOKEN de AsyncStorage (o en otro lugar) y configúralo para configurarlo en

 import {updateToke} from 'path_to_the_below_module'; updateToken({your token}). 

Aquí hay un código de fragmento que he hecho.

 import Axios from "axios"; import { AsyncStorage } from 'react-native'; const AUTH_TOKEN='AUTH_TOKEN'; const BASE_URL = 'http://localhost:5001/api/v1'; let authenticationToken = {}; export const updateToken = (token) => { AsyncStorage.setItem(AUTH_TOKEN, JSON.stringify(token)); authenticationToken = token; }; const networkRequest = Axios.create({ baseURL: BASE_URL, }); networkRequest.interceptors.request.use(config => { const bearer = `Bearer ${authenticationToken.access_token}`; if (bearer) { config.headers['Authorization'] = bearer; } console.log(config); return config; }, error => Promise.reject(error)); export default networkRequest; 

Simplemente forma de usarlo

 import networkRequest from '...pathtothemodule'; networkRequest.get('/user/info').then(....).catch(...); 

Tenga en cuenta que cada vez que actualice el token, asegúrese de llamar a updateToken ({token}) para mantenerlo actualizado.

Esta es otra alternativa que utilicé en mi proyecto, y deseo obtener sus ideas.