Skip to main content

Working with React

This guide with show you how to query data from a project using React.

Integrating your project's GraphQL API into a React app or site is simple, and this guide will take you through that process. Let's get started.

Our Starter Project

If you'd rather skip the detailed instructions and jump straight into a working example with React, check out a React Starter Project.

Don't know how to use a starter project? Read our docs on the subject.

Creating your React app

The most common way to create a React app is to use the npx create-react-app script. Read more about other ways to create a React app in the official React documentation.

Navigate to a directory where you keep your project folders and enter:

npx create-react-app your-project-name

You will have a react project generated for you, with boilerplate code.

That's all it takes to get running. You can learn how to customize and build your app in the React Docs.

This guide will show you how to integrate into your app.

Connecting your project

To connect to your project, you need your API Endpoint and an API key.

If you haven't created a project yet, follow this guide to do so.

If you already have a project, your API Endpoint will be in the admin UI. In the home tab, look for the "Useful Snippets" section.

Copy the API Endpoint and save it somewhere secure.

To get an API Key, you'll have to create one. Read our docs on creating an API Key here.

Using your endpoint and API key

danger

API keys used in frontend applications are exposed to the browser, even if you use environment variables. When you create an API Key, always use the fewest permissions necessary for your application. Learn more in our permissions guide.

To use environment variables in React, create a .env file in the root directory of your project, and define your variables. Just remember that you won't be able to access them without appending REACT_APP to the start of them. Here's an example below:

.env
REACT_APP_GRAPHQL_ENDPOINT=https://api.takeshape.io/project/6cdbcc52-5697-475b-872e-fcb6fd0e00d0/graphql

REACT_APP_GRAPHQL_KEY=61cbe1801a00482a831734ac29c27bfe

Now you're ready to add your GraphQL API to your projects safely.

Working with Fetch Requests

Standard fetch requests are the simplest way to query your project from React.

To query your project via a fetch request, you'll pass the API Key as a Bearer Token in the Authorization header, and add the query to a query property on the body.

Open up whichever component you want to perform the request in, and we'll create an example of how you would do it. In our case, we'll be using the app.js auto-generated for us by create-react-app. Here's an example:

app.js
async function fetchProducts(){
try{
const result = await fetch(
process.env.REACT_APP_GRAPHQL_ENDPOINT,
{
method: 'POST',
headers: {
"Authorization": `Bearer ${process.env.REACT_APP_GRAPHQL_KEY}`
},
body: JSON.stringify({
query: "query {getProductList{items{_id name price}}}"
})
});
} catch(error){
console.log("Failed to get products!", error);
}
}

To learn more about how to structure a fetch request, check out the MDN docs.

To add the code necessary to inject the data you've fetched into your component, you'll need to convert it to JSON. The below code should be added to your try/catch block at the end of the try, before the catch.

app.js
      //after the fetch request...
const {data} = await result.json();

const fetchedList =
data.getProductList.items.map(
item=><li key={item._id}>
<em>{item.name}</em>: {item.price}
</li>
});

return fetchedList;
} catch (error){
console.log("Failed to get products!", error);
}

The above code converts the result from your fetch request to json, then destructures the data property from. It then uses the Array Map method to create an array of JSX elements which contain the data we've fetched from our project, fetchedList.

After all of that, it returns fetchedList, the array of JSX elements, which can be added to our component.

To learn more about JSX elements, and how you can use them to structure React components, read the docs here.

The entire fetchProducts() function should look like this:

app.js
async function fetchProducts(){
try{
const result = await fetch(
process.env.REACT_APP_GRAPHQL_ENDPOINT,
{
method: 'POST',
headers: {
"Authorization": `Bearer ${process.env.REACT_APP_GRAPHQL_KEY}`
},
body: JSON.stringify({
query: "query {getProductList{items{_id name price}}}"
})
});
const {data} = await result.json();

const fetchedList =
data.getProductList.items.map(
item=><li key={item._id}>
<em>{item.name}</em>: {item.price}
</li>
});

return fetchedList;
} catch (error){
console.log("Failed to get products!", error);
}
}
Info

You'll notice the key prop on the <li> tags. This is because react requires dynamically-generated elements to have key props attached to them. For more information, check out this section of the React docs.

Adding your data to a React component

Because fetching is an asynchronous operation, your component may render before it's done retrieving the data you're fetching. To get around this, you must use the useEffect hook in React to call the fetch request as soon as the component renders. Then you can use the useState hook to trigger a re-render of the component once the data has arrived.

You'll also need to create an async function within the function you pass to useEffect, because if the main useEffect function is asynchronous, this may cause issues in React. To learn more about this issue, see this StackOverflow discussion. To solve the problem, we'll use an IIFE function, which executes immediately.

app.js
function App() {
const [productList, setProductList] = useState([
//React requires a key prop. Set something generic.
<li key='nothing-found-key'>Loading products...</li>
])

useEffect(() => {
//IIFE
(async function()=>{
setProductList(await fetchProducts())
})()
}, [])

//render code ...
}

Finally, we're ready to display our productList. You may have noticed with the above code that we set the productList to start with a default <li>. This element will show in our app until the fetch request completes. But in your own code, you could show a loading spinner or some sort of animation.

After your useEffect hook call, you'll want to return the JSX of your component. That will look something like this:

app.js
//... after useEffect

return (
<main>
<h1>
Product List:
</h1>

<ul>
{productList}
</ul>
</main>
);
}

In react, you must always return a single parent element. We're using the <main> element to make our HTML more semantic. Inside, we're creating a header that describes what we'll be showing, which is a list of products. We wrap our productList in a <ul>, since it will always be an array of <li> tags.

The final component will look like this:

app.js
function App() {
const [productList, setProductList] = useState([
<li key='LOADING'>Loading products...</li>
])

useEffect(() => {
(async()=>{
setProductList(await fetchProducts())
})()
}, [])

return (
<main>
<h1>
Product List:
</h1>

<ul>
{productList}
</ul>
</main>
);
}

Working with Apollo

Fetch isn't the only way to integrate your API into your React project. If you're interested in using your API with Apollo, check out our article on the process here.

Deploying your React site

Building your React site

If you want to statically build a React site, the process has a small wrinkle to it. First, use the npm build command:

npm run build

Now to run your site locally, you need to install the serve package.

npm install -g serve
serve -s build -l 4000

For the serve command, you can replace build with whatever the name of your build folder is. The number 4000 after -l can be replaced with whatever port you want to serve your site from. For more information on building and locally serving your React site, check out the official docs on the subject.

Hosting your React site or app

If you need help deploying your react site on the most popular hosts, here's a list of docs you can check out:

Still need help? Get in touch with us.