score:0

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

score:5

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(...)}

score:5

Doing it with hooks. I ran into a similar problem, but I was using react-redux with hooks. I did not want to lard up my interface code (i.e., react components) with lots of code dedicated to retrieving/sending information from/to the store. Rather, I wanted functions with generic names to retrieve and update the data. My path was to put the app's

const store = createSore(
   allReducers,
   window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
 );

into a module named store.js and adding export before const and adding the usual react-redux imports in the store.js. file. Then, I imported to index.js at the app level, which I then imported into index.js with the usual import {store} from "./store.js" The child components then accessed the store using the useSelector() and useDispatch() hooks.

To access the store in non-component front end code, I used the analogous import (i.e., import {store} from "../../store.js") and then used store.getState() and store.dispatch({*action goes here*}) to handled retrieving and updating (er, sending actions to) the store.

score:6

export my store variable

export const store = createStore(rootReducer, applyMiddleware(ReduxThunk));

in action file or your file need them import this (store)

import {store} from "./path...";

this step get sate from store variable with function

const state = store.getState();

and get all of state your app

score:7

It might be a bit late but i think the best way is to use axios.interceptors as below. Import urls might change based on your project setup.

index.js

import axios from 'axios';
import setupAxios from './redux/setupAxios';
import store from './redux/store';

// some other codes

setupAxios(axios, store);

setupAxios.js

export default function setupAxios(axios, store) {
    axios.interceptors.request.use(
        (config) => {
            const {
                auth: { tokens: { authorization_token } },
            } = store.getState();

            if (authorization_token) {
                config.headers.Authorization = `Bearer ${authorization_token}`;
            }

            return config;
        },
       (err) => Promise.reject(err)
    );
}

score:12

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.

score:14

You can use Middleware according to How can I access the store in non react components?:

Middleware

function myServiceMiddleware(myService) {
  return ({ dispatch, getState }) => next => action => {
    if (action.type == 'SOMETHING_SPECIAL') {
      myService.doSomething(getState());
      myService.doSomethingElse().then(result => dispatch({ type: 'SOMETHING_ELSE', result }))
    }
    return next(action);
  }
}

Usage

import { createStore, applyMiddleware } from 'redux'
const serviceMiddleware = myServiceMiddleware(myService)
const store = createStore(reducer, applyMiddleware(serviceMiddleware))

Further Reading: Redux Docs > Middleware

score:33

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 .

score:64

Found a solution. So I import the store in my api util and subscribe to it there. And in that listener function I set the axios' global defaults with my newly fetched token.

This is what my new api.js looks like:

// 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

Maybe it can be further improved, cause currently it seems a bit inelegant. What I could do later is add a middleware to my store and set the token then and there.

score:194

Export the store from the module you called createStore with. Then you are assured it will both be created and will not pollute the global window space.

MyStore.js

const store = createStore(myReducer);
export store;

or

const store = createStore(myReducer);
export default store;

MyClient.js

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

or if you used default

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

For Multiple Store Use Cases

If you need multiple instances of a store, export a factory function. I would recommend making it async (returning a promise).

async function getUserStore (userId) {
   // check if user store exists and return or create it.
}
export getUserStore

On the client (in an async block)

import {getUserStore} from './store'

const joeStore = await getUserStore('joe')

Related Query

More Query from same tag