0

I'm currently building a react-native application that uses react-redux to manage state. I'm attempting to dedup some authentication related logic by putting it into a service that isn't an extension of React's Component class. When a user logs in to the app, they are returned a user_token to validate subsequent API calls to the server. This token is stored in the auth reducer, so it would be available in a call of mapStateToProps via state.auth.user_token. I've defined a function in src/utils/fetch.js that performs API calls for me:

export function fetchAPI(endpoint, method = 'GET', data) {
  let url = 'http:localhost:3000/api/' + endpoint;

  let headers = { 'User-Token': 'XXXXXX' };

  if (method === 'POST') {
    headers['content-type'] = 'application/json';
  }

  let options = {
    method: method,
    headers: headers,
    mode: 'cors' // no-cors, cors, *same-origin
  };

  if (data) {
    options.body = JSON.stringify(data);
  }

  return fetch(url, options).then((response) => {
    ...

I'm wondering if there is a graceful / normal way of making this utility service aware of the values inside of state. I don't want to explicitly extract that property in every component that makes authenticated API calls - I'd basically have to do it everywhere and it feels redundant and verbose. Changing the method signature to accept this parameter feels bad:

export function fetchAPI(user_token, endpoint, method = 'GET', data) {
                         ^^^^^^^^^^ doesn't change while someone is logged in

But something like this feels better:

import storeProvider from './storeProvider';

export function fetchAPI(user_token, endpoint, method = 'GET', data) {
  const user_token = storeProvider.getUserToken();

  ... (go do great stuff with user_token)

Is there a conventional way to do this? Has anyone seen this sort of extracting of state into something that isn't a Container?

gards
  • 555
  • 1
  • 6
  • 18
  • Can you connect the parent to redux and pass down the information down as props to a child? But it should be really important to mention that connecting components when it has even some semblance in logic is a good thing. It is more performant and makes it a lot easier to rearrange components if you don't have to deal with child-parent prop passing and instead use redux as the universal source of truth – Andrew May 08 '18 at 20:24

1 Answers1

0

After you create the store export it. Import the store to the fetchAPI. Then use store.getState(), and extract the user token from the state.

Example:

// you'll to export the store after you use create store
import store from './store';

// this selector can be used across the app
const getUserToken = ({ auth }) => auth.user_token;

export function fetchAPI(user_token, endpoint, method = 'GET', data) {
  const user_token = getUserToken(store.getState());

  ... (go do great stuff with user_token)
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • Can't you hit race conditions if you do this? – Andrew May 08 '18 at 22:52
  • I tried this - doesn't seem to work. The reference to the store doesn't seem to update to reflect current state when being rerun. I also tried this using subscribe, which I would have figured would key the store in to changes to state (as suggested in one of the solutions in https://stackoverflow.com/questions/38460949/what-is-the-best-way-to-access-redux-store-outside-a-react-component?rq=1) but that didn't work either. – gards May 09 '18 at 18:44