Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helper component to handle CRUD API operations #94

Closed
gazpachu opened this issue Nov 16, 2016 · 6 comments
Closed

Helper component to handle CRUD API operations #94

gazpachu opened this issue Nov 16, 2016 · 6 comments

Comments

@gazpachu
Copy link

gazpachu commented Nov 16, 2016

How can I make a Helpers component to handle CRUD API methods and other utilities? I could use a regular component but I don’t need the render method

I need to access this.props.dispatch so using module.exports doesn’t work well for that, because when I pass this.props.dispatch as an argument to readAPI, I get dispatch is not a function(…):

Helpers.jsx:

import { readEndpoint, deleteEntity, createEntity, setEndpointHost, setEndpointPath, setAccessToken } from 'redux-json-api';
import { API_URL, API_PATH } from '../../constants/constants';

module.exports = {
    
   configAPI: function(token, dispatch) {
		dispatch(setEndpointHost(API_URL));
		dispatch(setEndpointPath(API_PATH));
		dispatch(setAccessToken(token));
	},
	
	readAPI: function(token, endpoint, dispatch, callback) {
		this.configAPI(token, dispatch);
		dispatch(readEndpoint(endpoint)).then(function(data) {
			callback(data);
		}.bind(this));	
	},
}

This is how I would call it:

Helpers.readAPI('my_API_token', 'whatever', this.props.dispatch, function(data) {
     // Do whatever
});
@gazpachu
Copy link
Author

gazpachu commented Nov 16, 2016

roman from Red Badger Team in the React London Slack group, was nice to give me this example. I'm just pasting it for your reference:

// define this inside your helper-module.js
import {
  createEntity,
  deleteEntity,
  readEndpoint,
  setAccessToken
  setEndpointHost,
  setEndpointPath
} from 'redux-json-api';
import { bindActionCreators } from 'redux';
import { API_URL, API_PATH } from '../../constants/constants';

const reduxJsonApiActions = {
  createEntity,
  deleteEntity,
  readEndpoint,
  setAccessToken
  setEndpointHost,
  setEndpointPath,
};

export default (dispatch, customActions) => ({
  ...bindActionCreators(reduxJsonApiActions, dispatch),
  configAPI: token => {
    dispatch(setEndpointHost(API_URL));
    dispatch(setEndpointPath(API_PATH));
    dispatch(setAccessToken(token));
  },
  readAPI: function (token, endpoint, callback) {
    this.configAPI(token, dispatch);
    dispatch(readEndpoint(endpoint)).then(function(data) {
      callback(data);
    });    
  },
  ...bindActionCreators(customActions, dispatch),
});

// inside your component.js
import getHelperActions from './helper-module.js';
import { bindActionCreators, connect } from 'redux';

const mapDispatchToProps = dispatch =>
  getHelperActions(dispatch, {
    yourAction,
    yourSecondAction
  });

class Cards extends Component {
  componentWillMount() {
    this.props.readAPI('token', 'http://endpoint', () => console.log('CALLBACK! ☎️'));
  }
  render() {
    ...
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Cards);

@egeriis
Copy link
Collaborator

egeriis commented Nov 18, 2016

I am not sure in which context you would need to do this. Could you elaborate on the purpose of doing it this way and how we could support this in redux-json-api?

@gazpachu
Copy link
Author

gazpachu commented Nov 18, 2016

Abstracting all the API related methods into a Helper module/component would free other components in the app from the repetition of having to call all the time setEndpointHost, setEndpointPath, setAccessToken, setHeader... That's a lot of config required for each API request, thus it's better to write it ONCE in one place rather than everytime we need to make an API request.

Maybe I'm missing something, but considering that in a React app, the order in which components mount is not really known or can be easily arranged, I needed to call all these previously mentioned methods prior to making the API request.

@egeriis
Copy link
Collaborator

egeriis commented Nov 21, 2016

You don't need to dispatch the configuring actions for each API request. The configuration is stored in state and will be used automatically for all requests.

@gazpachu
Copy link
Author

gazpachu commented Nov 24, 2016

@egeriis And in which file do you usually set the configuration to make sure it runs before any other component?

If I put it in the componentDidMount of my app.jsx, that doesn't guarantee that the configuration will be set before any other component. Sometimes the App component is loaded after a few other components, we cannot change that. It's the way React loads components.

On the other hand, I cannot put it before my index.jsx file, before the react router configuration, because the dispatch method requires a React component, isn't it?:

ReactDOM.render(
      <Provider store={store}>
        <Router onUpdate={() => window.scrollTo(0, 0), logPageView} history={history}>
            <Route path="/" component={App}>
                <IndexRoute component={Home} />;
                <Route path="/favourites" component={Cards} />
                <Route path="/inbox" component={Cards} />
                <Route path="/insights" component={Insight} />
                <Route path="*" component={NotFound} />
            </Route>
        </Router>
      </Provider>
, document.getElementById('react-root'));

It would help a lot if you specify in the Docs where is recommended to set the configuration.

@egeriis
Copy link
Collaborator

egeriis commented Nov 24, 2016

@gazpachu In your case, dispatching those actions in componentWillMount of App should be sufficient.

@egeriis egeriis closed this as completed Dec 28, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants