Next.js Updating Json (or database) on Click Event

Viewed 1096

Overview

I need to run server side code during a click event within the next.js framework.

I'm brand new to node, react, and next.js. I've always coded from scratch using PHP and JS. I want to be able to work with a team and build sites faster, so I thought it was a good idea to learn react. Next.js was the most appealing variation of react because it's seo friendly and great for single page webapps.

I'm stumped right now because nobody that I've seen online has talked about XHR post requests with triggers. They mainly talk about 'generating static pages' which is far from what I need to accomplish.

I've been researching this for days now to no avail so hopefully someone on here can help a noob out. I feel like this should be much more obvious. Please explain for someone with a heavy PHP background.

The Application

I'm making a simple task tracking application to teach myself next.js. To simulate a database, I'm fetching and saving to JSON files.

The first issue I ran into was with const fs = require('fs').promises;.

I could load json data using let tasks = require('./dtaTask.json'), but I could not update JSON files because 'fs' could not be used once the page was loaded.

I then learned about the getServerSideProps() method, allowing for 'fs' to be used by js.

I put my mgrTask code into the getServerSideProps() method which fixed the 'fs' issue.

I can send json data through the server, but I cannot send the object to update the json data later via a button press.

I know I could simply read the file using fetch, but I don't want to just read the file. I need to update it, and I need the object to be reusable for future query's.

Requirements

Page Load:

  • An object (mgrTask) is loaded that allows for the querying and updating of the database (JSON for testing).
  • All current tasks are fetched from the database using mgrTask and loaded into memory using an array.

Delete Trigger:

  • Task is removed from the client's browser.
  • mgrTask is either created again or called from page load.
  • mgrTask removes the task from the array when given the taskID.
  • mgrTask updates the database using the array in memory.

(firstpost.js) Page Code

import { Header } from '../../export/components/Header'
import { GenButton } from '../../export/components/genButton'
import { Task } from '../../export/components/tasks/Task'
import { useState } from 'react'
import { mgrTask } from '../../export/components/tasks/mgrTask'

export default function firstpost({ dtaTasks }) {
  const [tasks, setTasks] = useState(dtaTasks.getAll())

  // Delete Task
  function deleteTask(taskID) {
    console.log('delete ' + taskID)
    setTasks(tasks.filter((task) => task.taskID !== taskID ))
    dtaTasks.delete(taskID)
  }

  return (
    <div className="holder">
      <div className="container">
        <Header className="header" />
        <Task tasks={tasks} deleteTask={deleteTask} />
      </div>
      <GenButton className="centered" text='Home' href='/' />
    </div>
  )
}

export async function getServerSideProps() {
  var dtaTasks = []
  dtaTasks = mgrTask

  return {
    props: {
      dtaTasks
    }
  }
}

(mgrTask.js) Database Table Manager Code

const fs = require('fs').promises;
let tasks = require('./dtaTask.json')

export const mgrTask = {
  getAll: () => tasks,
  getById: id => tasks.find(x => x.id.toString() === id.toString()),
  find: x => tasks.find(x),
  create,
  update,
  delete: _delete
};

function create(task) {
  // generate new user id
  task.id = tasks.length ? Math.max(...tasks.map(x => x.id)) + 1 : 1;

  // set date created and updated
  task.dateCreated = new Date().toISOString();
  task.dateUpdated = new Date().toISOString();

  // add and save task
  tasks.push(task);
  saveData();
}

function update(id, params) {
  const task = tasks.find(x => x.id.toString() === id.toString());

  // set date updated
  task.dateUpdated = new Date().toISOString();

  // update and save
  Object.assign(task, params);
  saveData();
}

// prefixed with underscore '_' because 'delete' is a reserved word in javascript
function _delete(taskID) {
  // filter out deleted task and save
  tasks = tasks.filter(x => x.taskID.toString() !== taskID.toString());
  saveData();
}

function saveData() {
  fs.writeFileSync('data/tasks.json', JSON.stringify(tasks, null, 4));
}
1 Answers

Next.js has post request api support.

Attach the post request to a function that the button calls. Include a api directory in the pages folder. Create a file for handling the post request that includes mgrTask. Send the needed data to mgrTask to handle the database update.

Function Btn Calls

  async function updateTasks(allTasks) {
    const response = await fetch('../api/tasks.js', {
      method:'POST',
      body: {allTasks},
      headers: {
        'Content-Type': 'application/json',
      },
    })
    const res = await response
    console.log(res)
  }

Post Handling API

import { mgrTask } from '../../export/components/tasks/mgrTask'

export default function handler(req, res) {
  if (req.method === 'POST') {
    mgrTask.saveData(req.body.allTasks)
    res.status(201).json({ updatePage: 'if you need data from the server' })
  }
}

https://nextjs.org/docs/api-routes/introduction

Related