Skip to content

Instantly share code, notes, and snippets.

@matheusrod92
Created April 5, 2019 03:53
Show Gist options
  • Save matheusrod92/ecf3c9b6ff4d424098d3cd72709071ef to your computer and use it in GitHub Desktop.
Save matheusrod92/ecf3c9b6ff4d424098d3cd72709071ef to your computer and use it in GitHub Desktop.
React API Middleware to inject API Methods and State into component/container
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import rickAndMortyApi from './apis/rickAndMorty';
import withApi from './middlewares/withApi';
class App extends PureComponent {
handleMorty = () => {
const { getMorty } = this.props;
getMorty();
};
handleRick = () => {
const { getRick } = this.props;
getRick();
};
render() {
const {
errorMessage,
hasError,
isLoading,
payload,
status,
} = this.props;
return (
<div>
<button onClick={this.handleMorty}>Get Morty</button>
<button onClick={this.handleRick}>Get Rick</button>
<div>
<p><strong>errorMessage:</strong> {errorMessage}</p>
<p><strong>hasError:</strong> {String(hasError)}</p>
<p><strong>isLoading:</strong> {String(isLoading)}</p>
<p>
<strong>payload:</strong>
{payload && <img src={payload.image} alt={payload.name} />}
</p>
<p><strong>status:</strong> {status}</p>
</div>
</div>
);
}
}
App.propTypes = {
errorMessage: PropTypes.string,
hasError: PropTypes.bool,
isLoading: PropTypes.bool,
payload: PropTypes.shape({
image: PropTypes.string,
name: PropTypes.string,
}),
status: PropTypes.number,
getMorty: PropTypes.func.isRequired,
getRick: PropTypes.func.isRequired,
};
App.defaultProps = {
errorMessage: undefined,
hasError: false,
isLoading: false,
payload: {},
status: undefined,
};
export default withApi(rickAndMortyApi)(App);
import axios from 'axios';
export default {
getRick: () => axios.get('https://rickandmortyapi.com/api/character/1'),
getMorty: () => axios.get('https://rickandmortyapi.com/api/character/2'),
};
import React, { Component } from 'react';
const withApi = api => WrappedComponent => class ApiHOC extends Component {
state = {
errorMessage: undefined,
hasError: false,
isLoading: false,
payload: undefined,
status: undefined,
};
fetchEndpoint = endpoint => async () => {
this.setState({
errorMessage: undefined,
hasError: false,
isLoading: true,
payload: undefined,
status: undefined,
});
try {
const response = await endpoint();
this.setState({
errorMessage: undefined,
hasError: false,
isLoading: false,
payload: response.data,
status: response.status,
});
} catch (err) {
this.setState({
errorMessage: err.message,
hasError: true,
isLoading: false,
payload: undefined,
status: err.response.status,
});
}
};
apiCalls = () => {
if (!api) return {};
const apiKeys = Object.keys(api);
let apiMethods = {};
apiKeys.forEach((key) => {
apiMethods = {
...apiMethods,
[key]: this.fetchEndpoint(api[key]),
};
});
return apiMethods;
}
render() {
return (
<WrappedComponent {...this.props} {...this.apiCalls()} {...this.state} />
);
}
};
export default withApi;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment