Build a Next.js Interactive Web-Based Simple Survey App

Written by

in

Surveys are a powerful tool for gathering feedback, understanding user preferences, and making data-driven decisions. From market research to customer satisfaction, surveys provide valuable insights. In this tutorial, we’ll build a simple yet functional survey application using Next.js, a popular React framework, to demonstrate how to create interactive web-based surveys.

Why Build a Survey App with Next.js?

Next.js offers several advantages for this project:

  • Server-Side Rendering (SSR) and Static Site Generation (SSG): Improve SEO and initial load times.
  • Fast Refresh: Provides a seamless development experience.
  • Built-in Routing: Simplifies navigation within the application.
  • API Routes: Easily handle form submissions and data processing.
  • React Ecosystem: Leverage the vast React library ecosystem.

By using Next.js, we can create a performant, SEO-friendly, and maintainable survey application.

Project Setup and Prerequisites

Before we begin, ensure you have the following installed:

  • Node.js (version 14 or higher)
  • npm or yarn (package manager)

Let’s create a new Next.js project. Open your terminal and run:

npx create-next-app survey-app
cd survey-app

This command creates a new Next.js project named “survey-app” and navigates you into the project directory.

Project Structure

Our project structure will be relatively simple:

survey-app/
├── pages/
│   ├── index.js          // Main survey page
│   └── api/
│       └── submit.js     // API route for handling form submissions
├── components/
│   └── Question.js     // Component for individual survey questions
├── styles/
│   └── globals.css       // Global styles
└── package.json

Building the Survey Interface

We’ll start by creating the main survey page (pages/index.js). This page will render the survey questions and handle user interactions.

Open pages/index.js and replace the default content with the following:

import { useState } from 'react';
import styles from '../styles/Home.module.css';

const questions = [
  {
    id: 1,
    text: 'How satisfied are you with our service?',
    type: 'radio',
    options: ['Very Satisfied', 'Satisfied', 'Neutral', 'Dissatisfied', 'Very Dissatisfied'],
  },
  {
    id: 2,
    text: 'What could we improve?',
    type: 'textarea',
  },
];

export default function Home() {
  const [answers, setAnswers] = useState({});
  const [submitted, setSubmitted] = useState(false);

  const handleChange = (questionId, value) => {
    setAnswers({ ...answers, [questionId]: value });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const response = await fetch('/api/submit', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(answers),
      });

      if (response.ok) {
        setSubmitted(true);
        // Optionally, reset the form after submission
        // setAnswers({});
      } else {
        console.error('Submission failed');
        // Handle error (e.g., display an error message)
      }
    } catch (error) {
      console.error('Error submitting:', error);
      // Handle error (e.g., display an error message)
    }
  };

  return (
    <div>
      <main>
        <h1>Simple Survey</h1>
        {submitted ? (
          <p>Thank you for your feedback!</p>
        ) : (
          
            {questions.map((question) => (
              
            ))}
            <button type="submit">Submit</button>
          
        )}
      </main>
    </div>
  );
}

In this code:

  • We import the useState hook to manage the survey answers and submission status.
  • We define an array of questions, each with an ID, text, type, and options (for radio questions).
  • The handleChange function updates the answers state when a user interacts with a question.
  • The handleSubmit function sends the answers to an API route (we’ll create this next).
  • The component renders the survey questions using the Question component (we’ll create this next) or a thank-you message after submission.

Creating the Question Component

Next, let’s create a reusable Question component (components/Question.js) to render individual survey questions.

Create a file named components/Question.js and add the following code:

import React from 'react';

const Question = ({ question, value, onChange }) => {
  const handleChange = (e) => {
    onChange(question.id, e.target.value);
  };

  if (question.type === 'radio') {
    return (
      <div>
        <p>{question.text}</p>
        {question.options.map((option) => (
          <label>
            
            {option}
          </label>
        ))}
      </div>
    );
  } else if (question.type === 'textarea') {
    return (
      <div>
        <p>{question.text}</p>
        <textarea />
      </div>
    );
  }

  return null;
};

export default Question;

This component:

  • Receives a question object, the current value, and an onChange function as props.
  • Renders different input types based on the question’s type (radio buttons or a textarea).
  • Uses the onChange event handler to update the parent component’s state.

Styling the Survey

For basic styling, let’s modify styles/Home.module.css. Replace the existing content with the following:

.container {
  min-height: 100vh;
  padding: 0 0.5rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: #f5f5f5;
}

.main {
  padding: 5rem 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 80%;
  max-width: 600px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.main h1 {
  margin-bottom: 2rem;
  font-size: 2rem;
  color: #333;
}

.main form {
  display: flex;
  flex-direction: column;
  width: 80%;
}

.main label {
  display: flex;
  align-items: center;
  margin-bottom: 0.5rem;
  cursor: pointer;
}

.main input[type="radio"] {
  margin-right: 0.5rem;
}

.main textarea {
  margin-bottom: 1rem;
  padding: 0.5rem;
  border: 1px solid #ccc;
  border-radius: 4px;
  resize: vertical;
  font-family: inherit;
  width: 100%;
}

.main button {
  padding: 0.75rem 1.5rem;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 1rem;
  transition: background-color 0.2s ease;
  margin-top: 1rem;
}

.main button:hover {
  background-color: #3e8e41;
}

This CSS provides basic styling for the container, main content, headings, form elements, and button. Feel free to customize it to match your desired design.

Handling Form Submissions (API Route)

Now, let’s create an API route to handle the form submissions. This route will receive the survey answers and, in a real-world scenario, would save them to a database or perform other processing.

Create a file named pages/api/submit.js and add the following code:

export default async function handler(req, res) {
  if (req.method === 'POST') {
    try {
      const answers = req.body;
      // In a real application, you would save the answers to a database here.
      console.log('Survey answers:', answers);
      res.status(200).json({ message: 'Survey submitted successfully!' });
    } catch (error) {
      console.error('Error processing survey:', error);
      res.status(500).json({ message: 'Error submitting survey' });
    }
  } else {
    res.status(405).json({ message: 'Method Not Allowed' });
  }
}

This API route:

  • Checks if the request method is POST.
  • Retrieves the survey answers from the request body (req.body).
  • Logs the answers to the console (replace this with your database logic).
  • Sends a success response with a 200 status code.
  • Handles potential errors and sends an error response with a 500 status code.

Running the Application

To run the application, execute the following command in your terminal:

npm run dev
# or
yarn dev

This will start the Next.js development server. Open your web browser and navigate to http://localhost:3000 to view your survey application.

Testing the Survey

Test the survey by filling out the questions and clicking the submit button. Check your console to see the logged answers. You should also see the “Thank you for your feedback!” message after submission.

Common Mistakes and Troubleshooting

Here are some common mistakes and how to fix them:

  • Incorrect File Paths: Double-check that all file paths (e.g., in imports) are correct.
  • Missing Dependencies: Ensure you have installed all necessary dependencies. Run npm install or yarn install if needed.
  • CORS Errors: If you encounter CORS (Cross-Origin Resource Sharing) errors when submitting the form, ensure your API route is correctly configured to handle requests from your frontend. For development, you might need to install and configure a CORS middleware.
  • Typographical Errors: Carefully review your code for any typos, especially in variable names and component props.
  • Incorrect State Management: Verify that you are correctly updating and accessing the state variables using useState.

Key Takeaways and Best Practices

  • Component Reusability: The Question component demonstrates how to create reusable UI elements.
  • State Management: Using useState to manage form data.
  • API Routes: Using Next.js API routes to handle form submissions.
  • Error Handling: Implementing basic error handling to improve the user experience.
  • User Experience: Providing clear feedback after form submission.

Enhancements and Next Steps

This is a basic survey application. Here are some ideas for enhancements:

  • Database Integration: Store the survey answers in a database (e.g., MongoDB, PostgreSQL).
  • More Question Types: Add support for more question types (e.g., multiple-choice, rating scales, date pickers).
  • Validation: Implement form validation to ensure users provide valid input.
  • User Interface Improvements: Enhance the UI with more styling and better user experience.
  • Analytics: Integrate analytics to track survey responses.
  • Admin Panel: Create an admin panel to manage surveys and view results.

FAQ

  1. How do I deploy this application?
    You can deploy your Next.js application to platforms like Vercel, Netlify, or AWS. Vercel is particularly well-suited for Next.js applications and offers a simple deployment process.
  2. Can I use a different CSS framework?
    Yes, you can easily integrate CSS frameworks like Tailwind CSS, Bootstrap, or Material-UI into your Next.js project.
  3. How can I prevent spam submissions?
    Implement measures like CAPTCHA or reCAPTCHA to prevent automated spam submissions. You can also add rate limiting to your API route.
  4. How do I handle file uploads in the survey?
    You’ll need to use a library like react-dropzone or a similar file upload component. On the backend, you’ll need to handle the file upload and storage, typically using a service like Cloudinary or AWS S3.

Building this survey application provides a solid foundation for understanding how to create interactive web applications with Next.js. By applying the concepts and best practices discussed, you can create more complex and feature-rich applications. Remember to continuously refine your code, add enhancements, and adapt the application to meet your specific needs. The possibilities are vast, and with each iteration, you’ll gain valuable experience in web development.

As you continue to develop and refine your survey application, you’ll discover even more ways to leverage the power of Next.js. The combination of server-side rendering, API routes, and the React ecosystem creates a powerful and flexible platform for building modern web applications. The key is to keep learning, experimenting, and building on your existing knowledge to create something truly unique and valuable.