Skip to content

Instantly share code, notes, and snippets.

@colorfield
Last active January 16, 2018 22:05
Show Gist options
  • Save colorfield/6baae95d6211e45168e462a34ec93fcf to your computer and use it in GitHub Desktop.
Save colorfield/6baae95d6211e45168e462a34ec93fcf to your computer and use it in GitHub Desktop.
React fetch on the route
import React from 'react';
import Layout from '../../components/Layout';
import ItineraryListPage from './ItineraryListPage';
import { JSON_API_URL } from '../../constants/env';
const title = 'Audioguide';
async function action({ locale, fetch }) {
// Use Drupal locale (e.g. convert en-US to en).
const languageId = locale.substring(0, 2);
// Fetch the localized terms.
// Sort by weight is the default value, but we define it explicitly.
// Get only the parent term, this is defined via a boolean field because
// currently there is no JSON API way to get only parents.
const endpoint = `${JSON_API_URL}/${languageId}/jsonapi/taxonomy_term/itinerary?filter[field_is_parent][value]=1&filter[langcode][value]=${languageId}&sort=weight&include=field_image`;
const response = await fetch(endpoint, { method: 'GET' });
const terms = await response.json();
return {
chunks: ['itineraries'],
title,
component: (
<Layout>
<ItineraryListPage title={title} itineraries={terms} />
</Layout>
),
};
}
export default action;
import React from 'react';
import PropTypes from 'prop-types';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import s from './ItineraryListPage.css';
import ItineraryTeaser from '../../components/ItineraryTeaser';
import ItineraryListHeader from '../../components/ItineraryListHeader';
import { JSON_API_URL } from '../../constants/env';
class ItineraryListPage extends React.Component {
// @todo we should define all the propTypes
// including the relationships used for the image.
static propTypes = {
itineraries: PropTypes.shape({
data: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
}).isRequired,
).isRequired,
included: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
}).isRequired,
).isRequired,
}).isRequired,
};
getImageFromIncluded(imageId) {
let result = null;
const image = this.props.itineraries.included.filter(
obj => obj.id === imageId,
);
if (image[0]) {
result = `${JSON_API_URL}/${image[0].attributes.url}`;
}
return result;
}
/**
* Attaches the includes Url to the itineraries data.
*
* @returns {Array}
*/
itinerariesWithIncludedUrl() {
const itinerariesWithIncluded = [];
this.props.itineraries.data.forEach(itinerary => {
const tmpItinerary = itinerary;
if (itinerary.relationships.field_image.data !== null) {
const iconImageId = itinerary.relationships.field_image.data.id;
tmpItinerary.iconImageUrl = this.getImageFromIncluded(iconImageId);
}
itinerariesWithIncluded.push(tmpItinerary);
});
return itinerariesWithIncluded;
}
render() {
return (
<div>
<div className={s.container}>
<ItineraryListHeader />
<ul className={s.gridPage}>
{this.itinerariesWithIncludedUrl().map(itinerary => (
<li key={itinerary.id}>
<ItineraryTeaser
destination={`/itinerary/${itinerary.id}`}
itinerary={itinerary}
/>
</li>
))}
</ul>
</div>
</div>
);
}
}
export default withStyles(s)(ItineraryListPage);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment