React Native: Redux - Is it possible to dispatch to redux store from App.js?

2.6k Views Asked by At

I am working on a react native app and I have everything hooked up to a redux store so that I can manage data in that way.

I am curious about the possibility of dispatching data from the App.js component which at the moment I use to essentially route my app. The use case would be to make an API call in App.js and set data in redux store from there so that the app presumably makes that call every time it is opened. I know componentDidMount for instance runs the code once when the app is opened but then never again unless its closed and reopened. I assume that App.js might be better for something like this. If that assumption is incorrect my apologies as I am still learning.

In the example below, how would I run callApi and setData from App.js to the Redux Store if that is possible? Or should I avoid this an try to set a global variable?

Below is sample code:

App.js

 import React, {Component} from 'react';
    import {createBottomTabNavigator} from 'react-navigation-tabs'
    import { createAppContainer, createSwitchNavigator } from 'react-navigation';
    import { Ionicons } from '@expo/vector-icons';
    import { Provider } from 'react-redux';
    import { createStore } from 'redux';
    
    import ourReducer from './store/reducer';
    const store = createStore(ourReducer);
    global.x = 'https://volleybuddy.metis-data.site'
    
    
    import Home from './components/Home'
    import Profile from './components/Profile'
    import Login from './components/Login'
    import SignUp from './components/SignUp'
    import StartScreen from './components/StartScreen'
    
    export default class App extends Component {
    
    
      render(){
    
        return (
          
          <Provider store={ store }>
            <AppContainer/>
          </Provider>
        );
        }
    }
    
    const bottomTabNavigator = createBottomTabNavigator(
      {
        Home: {
          screen: Home,
          navigationOptions: {
            tabBarIcon: ({ tintColor }) => (
              <Ionicons  name="ios-home" size={25} color={tintColor}/>
              // <Icon name="qrcode" size={25} color={tintColor} />
            )
          }
        },
        Profile: {
          screen: Profile,
          navigationOptions: {
            tabBarIcon: ({ tintColor }) => (
              // <Icon name="search" size={25} color={tintColor} />
              <Ionicons  name="md-person" size={25} color={tintColor}/>
            )
          }
        },
      },
      {
        initialRouteName: 'Home',
        tabBarOptions: {
          activeTintColor: '#eb6e3d'
        }
      }
    );
    
    const RootSwitch = createSwitchNavigator({ 
      StartScreen,
      SignUp,
      Login,
      bottomTabNavigator
      });
    
    const AppContainer = createAppContainer(RootSwitch);

Reducer.js (I set up my reducer something like this)

import { combineReducers } from 'redux';

const INITIAL_STATE = {
    data: null
};

const ourReducer = (state = INITIAL_STATE, action) => {
    const newState = { ...state };

  switch (action.type) {
        
                    case "SET_DATA":
                      return{
                        ...state,
                        data: action.value
                      }
                    break;
  
  }
  return newState;
};


export default combineReducers({
  reducer: ourReducer,
});

Home.js (Lets just say if I want to move callApi to run also in App.js)

import React, {Component} from 'react';
import { connect } from 'react-redux';

class Home extends Component {

    //NOT REAL CODE, JUST CONCEPT
    callApi =() => {
        fetch(....)
        let data = response
        this.props.setData(data)
    }

  render() {
    return (
        <React.Fragment>
            <View>
                <Button onPress={this.callApi}>
                    <Text>toggle tracking</Text>
                </Button>
            </View>
        </React.Fragment>
    );
  }
}

const mapStateToProps = (state) => {
    
    const { reducer } = state
    return { reducer }
  };

  const mapDispachToProps = dispatch => {
    return {
      setData: (x) => dispatch({ type: "SET_DATA", value: x}),
    };
  };

  export default connect(mapStateToProps,
    mapDispachToProps
    )(Home)
2

There are 2 best solutions below

0
On

You can dispatch data from anywhere in the app as long as you can get a reference to the store using store.dispatch, in this case you can dispatch and action App component after the store is instantiated, but the App component itself is not connected to the store so it unable to re-render in response to changes on it, but this should not be a problem for you in this case.

0
On

Yes, It is possible.

I have a store.js file like this:

import { createStore, combineReducers, applyMiddleware} from 'redux'
import reducer from './reducers'
import thunk from 'redux-thunk';
const middleware =  applyMiddleware(thunk)
const store = createStore(reducer,middleware)



export default store;

So, in the App.js file I just need to import the store like this:

import store from './src/store'

And you can call to dispatch:

 store.dispatch({ type: "ACTION_EXAMPLE" });