How to Create a Survey Application Using Strapi and React.JS

Strapi - Jul 12 '22 - - Dev Community

This tutorial will walk you through the process of creating a survey app with Strapi and react.js, as well as how to use internationalization for the app.

Author: Popoola Temitope

Survey applications are software that companies use to get feedback from customers or employees on how well their products or services are performing. Because organizations can obtain customer or employee reviews of their services, survey applications play an important role in organization service analysis. The company will then work on the collected feedback to provide the best services that suit the expectations of the customers.

Many companies use surveys because it is one of the easiest ways to collect information from the outside world. Whether your company wants to collect opinions or wants you to complete a feedback form, a web survey is a good way to go.

Surveys can show you the problems your service solves (and the ones it doesn't) and give you insight into what you need to be doing to satisfy your customers. They'll show you more about your pricing schemes and tell you how you can improve based on what your customers say. In short, surveys should be built into every organization's strategy to get feedback from customers and prospects as well as a way to build trust with them.

In this tutorial, I'll walk you through the steps of creating a survey app with React.js using Strapi as the backend tool. Here's what it'll look like:

Survey Application

Prerequisites

To follow this tutorial, you should have:

  • Node.js v14 or v12 installed on your computer. To check your node version, use the node -v command.
  • NPM or Yarn installed on your computer.
  • Basic knowledge of React.js.

What is Strapi?

Strapi is an open-source Content API Framework that is used to build content-oriented applications. It can be used to build a simple blog or used to build complex e-commerce platforms like Shopify.

Strapi is written in Node.js and uses MongoDB as its database. It provides a rich set of features, including authentication and authorization, content management, data import/export, performance monitoring, etc.

What is React.js?

React.js is a library for creating user interfaces. It's a declarative, component-based UI library. It allows you to create reusable UI components that render using data models to describe how the component should be rendered.

React aims to address one problem: building large applications with data that changes over time. We want our apps to be fast and responsive no matter how much data they display or how many things happen on the page at once, so we need an efficient way of updating the view when data changes.

Why is A Survey Application Important?

There are many reasons why developers need to use surveys.

  1. They can get feedback from their customers about their products.
  2. They can know what features people want and how they want them implemented.
  3. It helps them improve the quality of their product and make changes accordingly.
  4. It also gives them an idea about the market share of their product, which will help them decide whether it is worth investing more time into the development process or not.

Features of Our Survey Application

The survey application that we will create will have the following features:

  • Random questions
  • 'Yes or No' questions
  • Localized questions
  • Form questions

Strapi Installation

Let's kick-start with our installation. Open the command line, and enter one of the following commands:

  • Yarn command:
    yarn create strapi-app survey-app --quickstart
Enter fullscreen mode Exit fullscreen mode

Or

  • npx command:
    npx create-strapi-app survey-app --quickstart
Enter fullscreen mode Exit fullscreen mode

The above command will install all the needed packages for the project. After the installation, the Strapi app will automatically be launched in the browser. Register with your details and it will take you to your dashboard page as shown below:

Strapi Dashboard

React.js Installation

Creating a React app is easy. The first step is to run the following commands on the terminal:

    npx create-react-app my-app
    cd my-app
    npm start
Enter fullscreen mode Exit fullscreen mode

The above command will create a directory for your new project and initialize it as a package. The React app must be installed under the my-project folder.

Building the Survey App

Now that we have done all the prep, let's dive right into building our survey app.

Creating Our App Collections on Strapi

In this simple survey app, we’ll create two content types named survey and response.

  • Survey Collection Type:

This collection type will contain all the survey questions with their options so that users can choose that response. We’ll also use an internationalization plugin to translate the survey questions into different languages.

Before we create the survey collection, let's add a new locale language to our application. To do this is simple. From your dashboard menu, click on Settings. Then, under the global settings sub-menu, click on internationalization.

To add the new language, click on the "add new locale" button and then select the language and save it. But for our survey application we’ll only add French (Canada) fr-CA, as shown below:

how to create internationalization in Strapi

Now, let's create the survey collection type. From your dashboard menu, click on Content-Type Builder, then click on Create New Collection Type. Enter the display name for the collection type and then click on advanced settings. Under advanced settings, make sure that you enable international and click on continue.

creating collection type in strapi

After that, we’ll add the necessary fields for the survey content type. The survey content type fills in the following fields:
i. question: (Text - Long Text)
ii. a: (Text - Short Text)
iii. b: (Text - Short Text)
iv. c: (Text - Short Text)

Creating fields in strapi

  • Response Collection Type:

This collection type is where all the survey responses will be stored. The response collection type will contain the following fields: Email, surveyQuestion, surveyResponse. To create the response collection type, follow the same steps as used in the survey collection type above.

Creating fields in strapi

Adding Questions to the Survey Collection

Let's add some of the survey questions to the survey collection type. To do this is simple. From the content manager menu, click on survey and then click the "Create new entry" button. Fill in the survey questions and their response options, then save it and click on publish. You can add as many survey questions as you like.

how to create new record in strapi

Adding Internationalization Questions

To add locale content for the survey collection type, on the survey collection page, click on the edit icon for each question. From the left-hand side, click on locale and select your preferred language. Fill in the survey question in the selected language, save and publish it.

how to publish locale content in strapi

Wrapping up the Backend

Before we move to frontend design, we need to ensure that survey and response content types are available via API call. Go to Settings, click Roles, and edit Public. Select all and click on save for both survey and response respectively.

Now we can make requests to survey and response collection types using http://localhost:1337/api/surveys/ and http://localhost:1337/api/responses/ restful endpoint from the front-end interface.

Strapi API Permission

Building the Frontend

In this tutorial, we’ll not focus on the styling, but from your React project, open app.css and replace the styling with the following code:

    // src/App.css
    .App {
        text-align: center;
    }

    .main {
        width: 99%;
        height: 500px;
        background-color: #e7e7e7;
        border-radius: 10px;
        margin-top: 70px;
        border: 4px solid #f3f3f3
    }

    .bar1 {
        width: 100%;
        height: 70px;
        border-top-right-radius: 10px;
        border-top-left-radius: 10px;
    }

    .bar2 {
        width: 70%;
        height: 27px;
        background-color: white;
        border-radius: 10px;
    }

    .bar3 {
        width: 100%;
        height: 27px;
        background-color: #f68e56;
        float: left;
        border-radius: 10px;
        color: white;
    }

    #surv {

        width: 90%;
        height: 380px;
        background-color: #f3f3f3;
        border-top-right-radius: 10px;
        border-top-left-radius: 10px;
        margin-left: 70px;
    }

    .divid1 {
        height: 200px;
        width: 440px;
        float: left;
        margin-left: 200px;
    }

    .divid2 {
        height: 200px;
        width: 440px;
        float: right;
    }

    .input {
        border: 2px solid #d5d5d5;
        font-size: 17px;
        background: #fbfbfb;
        height: 20px;
        padding: 8px;
        width: 400px;
    }

    .radio_option {
        width: 1100px;
        height: 430px;
        margin-left: 100px;
    }

    .radio {
        border: 2px solid #d5d5d5;
        font-size: 17px;
        background: #fbfbfb;
        height: 24px;
        padding: 8px;
        width: 24px;
    }
    .checkbox {
        border: 2px solid #d5d5d5;
        font-size: 17px;
        background: #fbfbfb;
        height: 24px;
        padding: 8px;
        width: 24px;
    }

    .container {
        width: 1100px;
        height: 430px;
    }

    .hid {
        display: none;
        width: 90%;
        height: 380px;
        background-color: #f3f3f3;
        border-top-right-radius: 10px;
        border-top-left-radius: 10px;
        margin-left: 70px
    }

    .view {
        display: inherit;
        width: 90%;
        height: 380px;
        background-color: #f3f3f3;
        border-top-right-radius: 10px;
        border-top-left-radius: 10px;
        margin-left: 70px
    }

    .btn {
        width: 100px;
        height: 32px;
        background-color: #f68e56;
        border-radius: 100px;
    }
Enter fullscreen mode Exit fullscreen mode

What Is Axios?

Axios is a tool to make HTTP requests and handle the responses. It's written on top of the Promise API and can be used in both the browser and on the server. It's fast, simple, and supports features like caching, timeout, and authentication.

We'll be using Axios to make requests to our Strapi project endpoint because of its capabilities and features. Let's get Axios up and running in our React app.

Axios Installation

To install Axios, navigate to your React project folder in the terminal and run the command below.

    npm install Axios
Enter fullscreen mode Exit fullscreen mode

Building the Application's Functionality

To add functionality to our project, open app.js in your code editor and paste in the following code, then save it.

    // src/App.js
    import React, { useState, useEffect } from 'react';
    import axios from 'axios';
    import './App.css';

    function App() {
        const [email, setemail] = useState('2');
        const [gender, setgender] = useState('3');
        const [question1, setQuestion1] = useState("");
        const [question2, setQuestion2] = useState("");
        const [question3, setQuestion3] = useState("");
        const [response1, setResponse1] = useState("");
        const [response2, setResponse2] = useState("");
        const [response3, setResponse3] = useState("");
        const [lang, setLang] = useState("en");
        const [QuestionNum1, setQuestionNum1] = useState(1);
        const [QuestionNum2, setQuestionNum2] = useState(2);
        const [button, setButton] = useState("Start Survey");
        const  getsurvey = async (value) => {

            let Tasks = await axios.get('http://localhost:1337/api/surveys?locale=' + value);
            setQuestion1(Tasks.data.data\[0\]["attributes"]);
            setQuestion2(Tasks.data.data\[QuestionNum1\]["attributes"]);
            setQuestion3(Tasks.data.data\[QuestionNum2\]["attributes"]);
            setQuestionNum1(prev => QuestionNum1 + 2);
            setQuestionNum2(prev => QuestionNum2 + 2);
        }



        const load = (value) => {
             getsurvey(value);
        }

        const [checkbox, setCheckbox] = useState({ box1: "", box2: "",box3: ""});


        const updateBox = (box, value) => {
            if (box === "1") {
                if (checkbox.box1 === value) {
                    value = ""
                }
                setCheckbox(previousState => {

                    return { ...previousState, box1: value }

                });

            }

            if (box === "2") {
                if (checkbox.box2 === value) {
                    value = ""
                }
                setCheckbox(previousState => {
                    return { ...previousState, box2: value }
                });
            }
            if (box === "3") {
                if (checkbox.box3 === value) {
                    value = ""
                }
                setCheckbox(previousState => {
                    return { ...previousState, box3: value }
                });
            }
        }



        const [page, setpage] = useState(0);
        const [page0, set0page] = useState('view');
        const [page1, set1page] = useState('hid');
        const [page2, set2page] = useState('hid');
        const [page3, set3page] = useState('hid');
        const [page4, set4page] = useState('hid');

        const addTask = async (quest, valu) => {
            let res = await axios
                .post("http://localhost:1337/api/responses/", {

                    "data": { "Email": email, "surveyQuestion": quest, "surveyResponse": valu}
                })

           .catch((err) => console.log(err));

        };

        useEffect(() => {
            setResponse3(prev => checkbox.box1 + "," + checkbox.box2 + "," + checkbox.box3);
        }, [checkbox])


        const next = () => {
            if (page === 0) {
                set0page(prev => "hid");
                set1page(prev => "view");
                setpage(prev => page + 1);
                setButton(prev => "Next Question");
            }
            if (page === 1) {
                set1page(prev => "hid");
                set2page(prev => "view");
                setpage(prev => page + 1);
                setButton(prev => "Next Question");
            }
            if (page === 2) {
                set2page(prev => "hid");
                set3page(prev => "view");
                setpage(prev => page + 1);
                setButton(prev => "Submit");
            }
            if (page === 3) {
                set3page(prev => "hid");
                set4page(prev => "view");
                setpage(prev => 4);
                setButton(prev => "New Survey");
                addTask(question1.question, response1);
                addTask(question2.question, response2);
                addTask(question3.question, response3);
                 getsurvey(lang);
            }
            if (page === 4) {
                set4page(prev => "hid");
                set2page(prev => "view");
                setpage(prev => 2);
                setButton(prev => "Next Question");
            }
        }
        return (
            <div className="App" >
                <div className="main">
                    <div className="bar1">
                        <center>
                            <span>Progress</span>
                            <div className="bar2">
                                <div className="bar3" >
                                    {page}/3
                                </div>
                            </div>
                        </center>
                    </div>
                    <div  id="surv" className={page0}>

                        <br />
                        <h2>welcome to my survey app</h2>
                        <div className="container">
                            <div className="divid1">
                                <br />
                                <input type="text" className="input" name="" placeholder="Email address" onChange={(event) => setemail(event.target.value)} />
                                <br /><br />
                                <label>Select Language</label>
                                <select className="input" onChange={(event) => load(event.target.value)} placeholder="Select Language">
                                    <option>Select Language</option>
                                    <option value="en">English </option>
                                    <option value="fr-CA">French</option>
                                </select>
                                <br />
                                <br />
                            </div>
                            <div className="divid2">
                                <br />
                                <input type="text" className="input" name="" placeholder="Gender" onChange={(event) => setgender(event.target.value)} />
                                <br /><br />
                            </div>
                        </div>
                    </div>
                    <div id="surv" className={page1}>
                        <br />
                        <h2>{question1.question}</h2>
                        <div className="container">
                            <div className="divid1">
                                <br />
                                <input type="text" className="input" name="" placeholder="Fullname" onChange={(event) => setResponse1(event.target.value)} />
                                <br />
                                <br />
                            </div>
                        </div>
                    </div>
                    <div id="surv" className={page2} hidden>
                        <br />
                        <h2>{question2.question}</h2>
                        <div className="radio_option">
                            <input type="radio" value="22" onClick={(event) => setResponse2(question2.a)} name="r" className="radio"  />
                            <label className="font1">{question2.a}</label>
                            <br /><br />
                            <input type="radio" value="22" name="r" className="radio" onClick={(event) => setResponse2(question2.b)}   />
                            <label className="font1">{question2.b}</label>
                            <br /> <br />
                            <input type="radio" value="ww" name="r" className="radio" onClick={(event) => setResponse2(question2.c)}   />
                            <label className="font1 magin1">{question2.c}</label>
                            <br /><br />
                        </div>
                    </div>
                    <div id="surv" className={page3} hidden>
                        <br />
                        <h2>{question3.question}</h2>
                        <div className="radio_option">
                            <input type="checkbox" name="e" className="checkbox" onClick={(event) => updateBox('1', question3.a)} />
                            <label className="font1">{question3.a}</label>
                            <br />
                            <br />
                            <input type="checkbox" onClick={(event) => updateBox('2', question3.b)} value="22" name="e" className="checkbox"   />
                            <label className="font1">{question3.b}</label>
                            <br />
                            <br />
                            <input type="checkbox" onClick={(event) => updateBox('3', question3.c)} value="." name="r" className="checkbox" />
                            <label className="font1">{question3.c}</label>
                            <br />
                            <br />
                        </div>
                    </div>
                    <div id="surv" className={page4}>
                        <br />
                        <h2>Survey completed</h2>
                        <div className="container">
                            <b> start another survey now</b>
                        </div>
                    </div>
                    <button className="btn" onClick={() => next()} > {button} </button>
                </div>
            </div>
        );

    }
    export default App;
Enter fullscreen mode Exit fullscreen mode

If you followed all the steps from the beginning, you should have your survey application running now.

creating a survey application using strapi internationalization plugin

How Does the Code Work?

Let’s explain how the code above works to get a better understanding of the application.

    const  getsurvey = async (value) => {

            let Tasks = await axios.get('http://localhost:1337/api/surveys?locale=' + value);
            setQuestion1(Tasks.data.data\[0\]["attributes"]);
            setQuestion2(Tasks.data.data\[QuestionNum1\]["attributes"]);
            setQuestion3(Tasks.data.data\[QuestionNum2\]["attributes"]);
            setQuestionNum1(prev => QuestionNum1 + 2);
            setQuestionNum2(prev => QuestionNum2 + 2);
        }
Enter fullscreen mode Exit fullscreen mode

From the above code, what the getsurvey() method does is that it uses Axios to make requests to the backend. The internationalization language to get from the Strapi backend is specified by the variable value parameter.

When the user clicks on the Start Survey button, then the survey questions are loaded from strapi based on the language selected by the user. If the language selected by the user is French, then the survey questions will be in French by making use of strapi internationalization plugin.

    const addTask = async (quest, valu) => {
            let res = await axios
                .post("http://localhost:1337/api/responses/", {

                    "data": { "Email": email, "surveyQuestion": quest, "surveyResponse": valu}
                })

           .catch((err) => console.log(err));

        };
Enter fullscreen mode Exit fullscreen mode

We use the addTask() method to store the user responses to the backend. Whenever the user is through with a set of survey questions, and when the user clicks on the submit button, addTask() will be triggered to send the responses to the backend.

    useEffect(() => {
            setResponse3(prev => checkbox.box1 + "," + checkbox.box2 + "," + checkbox.box3);
        }, [checkbox])
Enter fullscreen mode Exit fullscreen mode

We use the useEffect hook to update the values for multiple option questions. Whenever the box is checked or unchecked, we then update it with the corresponding value.

Conclusion

Congratulations! You have successfully created a survey application from scratch.

In this tutorial, you learned how to set up Strapi for a survey application using the React.js library for the front end. We also learned how to use internationalization in Strapi to offer content in different languages.

You can view the code for this article here.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .