Mattis Mattis - 26 days ago 19
React JSX Question

How would I dispatch an redux action from my API module?

I'm building an app in React Native, using the Redux methodology.

I want to be able to dispatch actions from my API "module".

Potentially, every API request could time out (or fail), and if that happens I want to dispatch an action to my global reducer (which handles the errorBar message and state). I'd rather not dispatch that message for every result (every API request) inside the scenes or components.

My structure is as follows (most content stripped):

index.android.js

import React from 'react';
import { AppRegistry } from 'react-native';

import configureStore from './app/store/configureStore'; // combines all reducers
const store = configureStore();

import RootContainer from './app/containers/rootContainer';
import { Provider } from 'react-redux';

const App = () => (
<Provider store={store}>
<RootContainer/>
</Provider>
);

// Register our app
AppRegistry.registerComponent('ReduxTest', () => App);


rootContainer:

import { connect } from 'react-redux';

import RootScene from '../components/scenes/RootScene';
import { hideSplash, showSplash, setSplashMessage } from '../actions/splashActions';

function mapStateToProps(state) {
return {
global: state.globalReducer,
splash: state.splashReducer
};
}

export default connect(
mapStateToProps,
{
hideSplash: () => hideSplash(),
showSplash: () => showSplash(),
setSplashMessage: (message) => setSplashMessage(message)
}
)(RootScene);


RootScene.js

import React, { Component } from 'react';

import Splash from '../views/Splash';
import ErrorBar from '../elements/ErrorBar';

import { View, Text, StyleSheet } from 'react-native';

import api from '../../helpers/api';

class RootScene extends Component {
constructor(props) {
super(props);
this.state = {};
}

componentWillMount() {
api.checkConnectivity().then(response => {
// Hide splash, etc, optimally error states could be handled inside of "api"

});
}

render() {
return (
<View style={styles.rootWrapper}>
<ErrorBar props={this.props.global.errorBar}/>
<Splash/>
</View>
);
}

}

const styles = StyleSheet.create({
rootWrapper: {
flex: 1
}
});

export default RootScene;


api.js

const api = {
checkConnectivity() {
return _buildRequest({ endpoint: '/version' }).then(_makeRequest);
}
};

module.exports = api;


const _buildRequest = (request_data) => {
// ...
};

const _makeRequest = (request_object) => {
// ...
};


I'm aware that my stripped out code above is missing the actions to change the state of the errorBar.

If the way I'm structuring the app is completely nuts, I'm all ears.

Answer

Instead of API as "module", try to use it as a middleware. Therefore you will have access to dispatch() on your context.

The idea is dispatching the actions and based on the action your middleware will "decide" to call your api. In case of error the middleware can dispatch your default error action.

This post might help you: http://www.sohamkamani.com/blog/2016/06/05/redux-apis/

You can also use redux-api-middleware: https://github.com/agraboso/redux-api-middleware

Comments