javascriptreactjsaxios

Title: React App: Task Edit Doesn’t Update Display Until Page Refresh


I’m building a to-do app in React with a Node.js/Express backend and PostgreSQL as my database. The app allows users to add, edit, and delete tasks, which are stored in the database.

The problem I’m facing is with editing tasks: when I submit an edit, the change doesn’t display immediately on the page. The edited task only shows correctly if I manually refresh the page. I’d like to understand why this isn’t updating in real-time and how to fix it.

App.js (React Component) :

import React, { useEffect, useState } from "react";
import './App.css';
import Header from "./components/Header";
import AddTask from "./components/AddTask";
import ListNote from "./components/ListNote";
import axios from 'axios';

function App() {
  const [isFormVisible, setIsFormVisible]= useState(false);
  const[notes, setNotes]= useState([]);
  const [noteToEdit, setNoteToEdit] = useState(null);

  useEffect(() => {
    const fetchNotes = async () => {
      try {
        const response = await axios.get('http://localhost:8000/todos'); 
        setNotes(response.data); // Set the notes from the backend response
        console.log("Fetched tasks:", response.data);
      } catch (error) {
        console.error('Error fetching notes:', error);
      }
    };
    
    fetchNotes(); // Call fetchNotes when the component loads
  }, []);

  const handleAddNewTask = () => {
    setIsFormVisible(true); // Show the form when button is clicked
    setNoteToEdit(null); // Reset noteToEdit when adding a new task
  };

  const handleCloseForm = () => {
    setIsFormVisible(false);
  };

    // 2. Add new note to backend (POST Request)
    async function addNote(note) {
      try {
        if (noteToEdit !== null) {
          // Edit mode: update the existing note
          const response = await axios.put(`http://localhost:8000/todos/${noteToEdit.id}`, note);
          setNotes(prevNotes =>
            prevNotes.map((noteItem) =>
              noteItem.id === noteToEdit.id ? response.data : noteItem
            )
          );
          setNoteToEdit(null); // Reset edit mode
        } else {
          // Add new note (POST)
          const response = await axios.post('http://localhost:8000/todos', note);
          const newNote = response.data;
          setNotes(prevNotes => [...prevNotes, newNote]);
        }
      } catch (error) {
        console.error('Error adding/updating note:', error);
      }
      setIsFormVisible(false); // Close the form after submit
    }

    async function deleteNote(id) {
      try {
        await axios.delete(`http://localhost:8000/todos/${id}`);
        setNotes(prevNotes => prevNotes.filter((noteItem) => noteItem.id !== id));
      } catch (error) {
        console.error('Error deleting note:', error);
      }
    }

    function editNote(id) {
      setIsFormVisible(true);
      const noteToEdit = notes.find((noteItem) => noteItem.id === id);
      setNoteToEdit(noteToEdit); // Store the note to edit it later
    }

const handleDisappear = () => {
    setIsFormVisible(false);
  };

  return (
    <div className="app">
      
      <Header onAddNewTask={handleAddNewTask}/>
      {isFormVisible && <AddTask  onSubmit={handleDisappear} onAdd={addNote} onClose={handleCloseForm} note={noteToEdit} />}
      {notes.map((noteItem) => {
        return <ListNote  
        key={noteItem.id}
        id= {noteItem.id}
        title= {noteItem.title}
        onEdit={() => editNote(noteItem.id)} // Passing index for edit
        onDelete={() => deleteNote(noteItem.id)}
        />;

      }) }
      

    </div>
  );
}

export default App;

Server.js

const PORT = process.env.PORT ?? 8000
const express = require('express')
const cors = require('cors')
const app = express()
const pool = require('./db')

app.use(cors());
app.use(express.json());

app.get ('/todos', async (req,res) => {
    try{
    const todos = await pool.query('SELECT * from todos')
    res.json(todos.rows)

    } catch (err) {
        console.error(err);
    }
})

app.post ('/todos', async (req,res) => {
    try {
        const { title, content }= req.body;

        if (!title || !content) {
            return res.status(400).json({ error: "Title and description are required." });
        }

        const newTodo = await pool.query('INSERT INTO todos (title, content) VALUES($1, $2) RETURNING *', [title, content]);
        res.json(newTodo.rows[0]);  
    } catch (err) {
        console.error(err.message);
        res.status(500).send('Server error');
    }

})

// PUT request to update a todo
app.put('/todos/:id', async (req, res) => {
    try {
        const { id } = req.params;  // Get todo ID from the URL
        const { title, content } = req.body;  // Destructure data from request body
        await pool.query(
            'UPDATE todos SET title = $1, content = $2 WHERE id = $3',
            [title, content, id]
        );
        res.json('Todo updated successfully!');
    } catch (err) {
        console.error(err.message);
        res.status(500).send('Server error');
    }
});

// DELETE request to remove a todo
app.delete('/todos/:id', async (req, res) => {
    try {
        const { id } = req.params;  // Get todo ID from the URL
        await pool.query('DELETE FROM todos WHERE id = $1', [id]);
        res.json('Todo deleted successfully!');
    } catch (err) {
        console.error(err.message);
        res.status(500).send('Server error');
    }
});



app.listen(PORT, ()=> console.log (`server running on PORT ${PORT}`) )

Screenshot :

enter image description here


Solution

  • In your addNot function you are not returning the new list returned by the map. Please add the "return" keyword to your map like this:

     if (noteToEdit !== null) {
              // Edit mode: update the existing note
              const response = await axios.put(`http://localhost:8000/todos/${noteToEdit.id}`, note);
              setNotes(prevNotes => {
                return prevNotes.map((noteItem) =>
                  noteItem.id === noteToEdit.id ? response.data : noteItem
                )
              }
              );
              setNoteToEdit(null); // Reset edit mode
            }
        );
    

    Also, it seems like in your server side you're only returning a JSON text instead of the actual JSON to be displayed on the FrontEnd,

    Try updating this:

    res.json('Todo updated successfully!');
    

    to

    const todo = await pool.query(
                'UPDATE todos SET title = $1, content = $2 WHERE id = $3',
                [title, content, id]
            );
    res.json({message: 'Todo updated successfully!', data: {todo.rows[0]} });