Skip to main content

Use TakeShape with React

TakeShape can integrate with any frontend framework, and of course that includes React!

Integrating your TakeShape 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 an example of TakeShape working with React, check out our React Starter Project!

Don't know how to use a TakeShape 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 simply show you how to integrate TakeShape into your app.

Connecting your TakeShape project#

Before we get started, you'll need a TakeShape project API Key and API Endpoint. If you haven't created a TakeShape project yet, you can do that by following our docs on creating new projects.

Otherwise, you'll find the API Endpoint in your project on the TakeShape web client. In the home tab, look in the bottom right of your screen for a section called Useful Snippets.

Copy the API Endpoint. You'll need this to connect your Scully project to TakeShape.

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

Protecting your Project information#

Although environment variables protect your data from exposure in many circumstances, they do not do so in React projects. They will unfortunately be exposed in the JS of your site. Read the React docs about this issue for more information.

In order to protect your project, you'll need to create a read-only API Key. Check out our docs on creating API keys to learn more.

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_TAKESHAPE_ENDPOINT=https://api.takeshape.io/project/6cdbcc52-5697-475b-872e-fcb6fd0e00d0/v3/graphql
REACT_APP_TAKESHAPE_KEY=61cbe1801a00482a831734ac29c27bfe

Now you're ready to add TakeShape to your projects safely!

Using TakeShape with Fetch Requests#

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

To query your TakeShape project with 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_TAKESHAPE_ENDPOINT,        {            method: 'POST',            headers: {            "Authorization": `Bearer ${process.env.REACT_APP_TAKESHAPE_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.

In order 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_TAKESHAPE_ENDPOINT,        {            method: 'POST',            headers: {            "Authorization": `Bearer ${process.env.REACT_APP_TAKESHAPE_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. In order to get around this, you must use the useEffect hook in React to call the fetch request as soon as the component renders, then 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>  );}

Using TakeShape with Apollo#

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

Deploying your React site#

Building your React site#

If you simply 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 serveserve -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 confused? Ask for help!. We'd love to solve your problem.