Table Of Contents


Phone Directory: Writing to a file using NextJS

Phone Directory: Writing to a file using NextJS

profile-image

Milan Poudel

March 28, 2022

There comes a time when we are developing a static application, we need at least a way a user can contact us, be it any informational website or a portfolio. Imagine you are creating a website and there is no any backend to it. Additionally, you don't want to pay for any service.


Client side frameworks or libraries like ReactJS definitely can't help with file access and writing, but NextJS provides us an API which we will use to create a new file and write content with it. This method is definitely only meant for small applications and static websites.


Creating a new NEXTJS Project


Assuming that we are already familiar with NextJS and at least know the basics, we will proceed to create a new nextjs project. To create a new project, we use the following commands below either in terminal or in the supported editor.


npx create-next-app@latest


Hopefully, our new project is created. We will have pages folder inside our new project and definitely an "api" folder inside it. We can leverage this folder to allow us use the methods of file access and writing.


Let's first create a new page named "contact.tsx" or any name as you like. And add some jsx and styling to it.


//pages/contact.tsx
import React from 'react'

const Contact = () => {
  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    console.log('Form Submitted')
  }
  return (
    <div className="container">
      <div>
        <form className="contact-form" onSubmit={handleSubmit}>
          <h1>Phone Directory</h1>
          <input type="text" placeholder="Name" required className="contact-form-field" />
          <input type="email" placeholder="Email" required className="contact-form-field" />
          <input type="phone" placeholder="Phone" required className="contact-form-field" />
          <button type="submit" className="contact-form-button">
            Submit
          </button>
        </form>
      </div>
    </div>
  )
}


export default Contact


Styling our Contact Form:


Here's the styling of our contact form.


// styles/contact.css

.container {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background: blue;
}

.contact-form {
  margin: 0 auto;
  width: 50%;
  padding: 30px;
  background: #fff;
  border-radius: 5px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
  width: 470px;
  text-align: center;
}

.contact-form h1 {
  margin-bottom: 20px;
  color: #333;
  font-size: 24px;
  font-weight: 700;
}

.contact-form-field {
  margin-bottom: 20px;
  border: 1px solid #ccc;
  border-radius: 5px;
  width: 100%;
  padding: 10px;
}


.contact-form-button {
  background: #333;
  color: #fff;
  border: none;
  border-radius: 5px;
  padding: 10px 20px;
  cursor: pointer;
}



Our contact form will look like this after styling




Creating an async function for writing a file


With this all styling and UI setup, we are all ready to create a functionality. So, we will create a new function inside an "api" folder. It will help us create a new file and append contents to it using POST method.


//pages/api/contact.ts
import { appendFile } from 'fs'
import { NextApiRequest, NextApiResponse } from 'next'
import path from 'path'


const writeAFile = async (req: NextApiRequest, res: NextApiResponse) => {
  const { data } = req.body
  try {
    if (req.method === 'POST') {
      const filePath = path.join(process.cwd(), 'public', 'contacts.txt')
      // Change the file name as needed//line break with each post request
      const fileContent = `${data}\n`
      await appendFile(filePath, fileContent, (error) => {
        if (error) throw new Error('Error writing to file')
      })
      res.status(200).json({ message: 'New content added successfully.' })
    }
  } catch (error) {
    res.status(500).json({ error: 'Error creating a new contact' })
  }
}
export default writeAFile


Few points to be noted:


  • Here we are trying to join a path and create a file with it. Here, "process.cwd()" will give us the current path of the project and we will be creating a new file named "contacts.txt" inside our public directory.


  • Here "appendfile" is an asynchronous function that we get from "fs" module which is related with file system functionality.


Integrating writeFile API function


Let's replace our "handleSubmit" function from above which we attached on form onsubmit event. We also need to set values of our input field. So we will manage their values using setState.


import { useState } from 'react'

const Contact = () => {
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')
  const [phone, setPhone] = useState('')

  //replaced with new submit handler to call our contact api we created

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    const formattedData = `Name: ${name}\nEmail: ${email}\nPhone: ${phone}\n\n`
    try {
      const res = await fetch('/api/contact', {
        method: 'POST',
        body: JSON.stringify({ data: formattedData }),
        headers: {
          'Content-Type': 'application/json'
        }
      })
      if (res) {
        alert('Contact saved successfully')
      }
    } catch (e) {
      alert('Something went wrong while saving contact, please try again.')
    }
  }
  return (
    <div className="container">
      <div>
        <form className="contact-form" onSubmit={handleSubmit}>
          <h1>Phone Directory</h1>
          <input type="text" placeholder="Name" required className="contact-form-field" onChange={(e) => setName(e.target.value)} />
          <input type="email" placeholder="Email" required className="contact-form-field" onChange={(e) => setEmail(e.target.value)} />
          <input type="phone" placeholder="Phone" required className="contact-form-field" onChange={(e) => setPhone(e.target.value)} />
          <button type="submit" className="contact-form-button">
            Submit
          </button>
        </form>
      </div>
    </div>
  )
}

export default Contact


After this, when we will submit a form, we will see a folder created in our public folder named "contacts.txt" which will have all the contact information that we havesubmitted.


Conclusion:


Writing to a file is a handy way to save some content saved in a project. With the use of NextJS that helps us write a backend or api service, we can leverage it's power to access file utilities. Hence, NextJS has a come a long way to establish itself as a full stack framework for small to mid level projects.

Programming | Coding | Learning

Subscribe to learn about new technology and updates. Join over 1000+ members community to stay up to date with latest articles.

© 2024 Code With Milan. All rights reserved.