We created a basic, working, React application in Building the Base application.
Now, we will walk through the steps for configuring Drupal 8 to expose our content and accept connections from our application. Then we will create a Home page in our React application which will display all of the content relating to our Articles content type from Drupal.
In Drupal, we will need to enable the required core modules to gain access to the API.
Note: The following paths are based on the a Drupal instance for training at https://headless.mobomo.net. This will need to be changed to point to your Drupal instance.
- Log in as an administrator.
- Go to
https://headless.mobomo.net/admin/modules
. - Enable the following modules in Web Services:
- HAL
- HTTP Basic Authentication
- Restful web services
- Serialization
For this step, we will need to create a View inside of Drupal to expose the content we would like to display in our application.
- Go to
https://headless.mobomo.net/admin/structure/views/add
. - For our example, we will enter the following:
- View Name :
Articles API
- View Settings -> type :
Article
- REST Export Settings
- Enable
Provide a REST export
- REST export path:
api/articles
- Enable
- Save
- View Name :
Note: These changes will only need to be added if our Drupal instance is running on a different domain than our React application.
For this, we will need to add some changes to our services.yml
. This can be found in sites/default/
. If the file does not exist, you can copy default.services.yml
over to services.yml and then add this to the bottom of the file.
Note: allowedOrigins
should be set to the domain you will access the API from, for security reason. For our example, we have set it to *
which indicates that any domain can access this API.
cors.config:
enabled: true
allowedHeaders: ['x-csrf-token', 'content-type']
allowedMethods: ['GET', 'POST', 'PATCH', 'DELETE']
allowedOrigins: ['*']
exposedHeaders: false
maxAge: false
supportsCredentials: true
- Axios: Allows us to make our HTTP requests from React to interact with our Drupal API.
- React Router DOM: Allows for us to link to other components.
Note: These commands will need to be run in the root directory.
npm install --save axios react-router-dom
We are going to need to create a landing page to display our Articles. To do this, we will need a new component. Let's start by creating a folder named components
in the Base
directory to store all of our components we will create going forward.
Then, let's create a directory specific to this component named Home
. We can add any files related to our Home component here, such as CSS files.
Now let's create our script Home.js
inside of the Home
folder.
This script will do the following.
- Make a request using Axios to get a session token from Drupal.
- Attach the token to the header to make another request to our API we created earlier, and collect the data in JSON format.
- Take the returned Articles and pass them into our articles state defined in the constructor.
import React from 'react';
import axios from "axios";
class Home extends React.Component {
constructor() {
super();
this.state = { articles: [] };
}
componentWillMount(){
const component = this;
const baseURL = 'https://headless.mobomo.net';
const tokenURL = baseURL + '/rest/session/token';
const req = axios.get(tokenURL);
req.then((response) => {
const token = response.data;
this.ajax = axios.create({
baseURL,
headers: {
'X-CSRF-Token': token,
}
});
this.ajax.get('/api/articles?_format=json').then(function(articles) {
component.setState({
articles: articles.data
});
});
});
}
};
export default Home;
Let's start by creating a new directory for this component named ArticleTeaser
in the components
folder.
This will be our sub-component of the Home component. The purpose of this is to take in the data from Home.js
and render a teaser display for each article.
Now let's create our script ArticleTeaser.js
inside of the ArticleTeaser
folder.
This script will do the following.
- Declare the properties we will need from our API.
- Define the types of each property.
- Create the markup we will use to display the article teaser.
import React from 'react';
import PropTypes from 'prop-types';
const ArticleTeaser = ({title,content,image}) => {
return (
<div>
<img src={image.url} alt={image.alt} />
<h2>{title}</h2>
{content}
</div>
);
};
ArticleTeaser.defaultProps = {
title: '',
content: '',
image: {},
};
ArticleTeaser.propTypes = {
title: PropTypes.string.isRequired,
content: PropTypes.string.isRequired,
image: PropTypes.shape({
url: PropTypes.string,
alt: PropTypes.string,
}),
};
export default ArticleTeaser;
Now that we created an article teaser component, we can pass the data from our API to the component.
To do this, we will first need to include ArticleTeaser.js
import ArticleTeaser from "../ArticleTeaser/ArticleTeaser";
Now that we have a access to the component, we can create the render function and define what to display on the home page. This will:
- Loop through all of the articles retrieved from our API request.
- Create a new Article Teaser.
- Assign the property keys as defined in Step 3 a value from our articles state.
render() {
return(
<div align="center">
<h1>All Articles</h1>
{this.state.articles.map(({title, field_image, body}, index) => (
<ArticleTeaser
key={index}
title={title[0].value}
image={field_image[0]}
content={`${body[0].value.substring(0,250)}...`}
/>
))}
</div>
)
};
Now that we have created a directory of all the components we need, we will update App.js
to include our new home page.
Our App.js
file is going to act as a router for any page we create. To do so, we first need to install React Router DOM.
Note: This command will need to be run in the root directory.
npm install react-router-dom
We will then update our file to include the Home component and define our route.
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router,
Route,
} from 'react-router-dom';
import Home from './components/Home/Home';
class App extends React.Component {
render() {
return (
<Router>
<div>
<Route exact path="/" component={Home} />
</div>
</Router>
);
}
}
// rendering into the DOM
ReactDOM.render(<App />, document.getElementById('app'));
We now have a working React application using Drupal as a backend!
Note: This command will need to be run in the root directory.
If you are manually configuring the application in the Base
directory you will use
npm run base
Otherwise you can build from our Checkpoint1
directory which includes all of the changes we have completed so far.
npm run cp1
Go to http://localhost:3000/.
When you are ready you can continue with Starting from Checkpoint 1.