0

I am creating a front end app with NextJS 13 and fetching data from JSON placeholder. As the API docs say, data does not persists on the server.

My issue is that i am "creating" a new post which is being faked by the api so i cannot update it with a PUT request as the other posts that i am fetching from the API. Or at least that is what i understand.

So how can i update my recently "created" post?

This is my List of Posts (ListOfPosts.jsx)

'use client'
import { useEffect, useState } from "react";
import Link from "next/link";
import axios from "axios";
import PostItem from "./PostItem";

export default function ListOfPosts() {
    const [posts, setPosts] = useState([]);
    const [loading, setLoading] = useState(true);
    const [newPostTitle, setNewPostTitle] = useState('');
    const [newPostBody, setNewPostBody] = useState('');    
  
    useEffect(() => {
      const fetchPosts = async () => {
        try {
          const response = await axios.get(
            'https://jsonplaceholder.typicode.com/posts'
          );
          setPosts(response.data);
          setLoading(false);
        } catch (error) {
          console.log(error);
        }
      };
  
      fetchPosts();
    }, []);

    
  
    const addPost = async (e) => {
      e.preventDefault();
  
      try {
        const response = await axios.post(
          'https://jsonplaceholder.typicode.com/posts',
          {
            title: newPostTitle,
            body: newPostBody,
            userId: 1,
          }
        );
  
        const newPost = response.data;
        console.log('Response from creating post:', response);
        console.log('New post created:', newPost);
  
        setPosts((prevPosts) => [...prevPosts, newPost]);
        // Reset form inputs
        setNewPostTitle('');
        setNewPostBody('');
      } catch (error) {
        console.error('Error creating post:', error);
      }
    };
  
    const updatePost = async (postId, updatedTitle, updatedBody) =>{
        console.log('Updating post with ID:', postId);
        const res = await axios.put(`https://jsonplaceholder.typicode.com/posts/${postId}`,{
            id: postId,
            title: updatedTitle,
            body: updatedBody,
            userId: 1
        })
       
        setPosts((prevPosts) =>
        prevPosts.map((post) =>
          post.id === postId ? { ...post, title: updatedTitle, body: updatedBody } : post
        )
      );
    }

    if(loading){
        return <h1>Loading...</h1>
    }

    return (
      <div className="flex flex-col gap-4 items-center">
        <div className="">
          <h2>Create New Post</h2>
          <form onSubmit={addPost}>
            <div>
              <label htmlFor="title">Title:</label>
              <input
                name="title"
                type="text"
                id="title"
                value={newPostTitle}
                onChange={(e) => setNewPostTitle(e.target.value)}
                required
                className="rounded text-black bg-transparent"
              />
            </div>
            <div>
              <label htmlFor="body">Body:</label>
              <input
                type="text"
                id="body"
                value={newPostBody}
                onChange={(e) => setNewPostBody(e.target.value)}
                required
                className="rounded bg-transparent text-black"
              />
            </div>
            <button type="submit">Create Post</button>
          </form>
        </div>
        <div className="flex flex-col gap-4 w-full items-center ">
        {posts.map((post) => (
          <PostItem key={post.id} post={post} updatePost={updatePost} />
        ))}
        </div>
      </div>
    );
  }

And this is my PostItem.jsx

'use client'
import React, { useState } from 'react'
import { GiCancel } from 'react-icons/gi';
import { RiSave3Fill } from 'react-icons/ri';
import { GrEdit } from 'react-icons/gr';

function PostItem({ post, updatePost }) {

    const [ isEditing, setIsEditing ] = useState(false);
    const [updatedTitle, setUpdatedTitle] = useState(post.title);
    const [updatedBody, setUpdatedBody] = useState(post.body);

    if (!post) {
      return null;
    }
    
    const handleEdit = (postId) => {
        setIsEditing(true);
    }

    const handleCancelEdit = (postId) => {
        setIsEditing(false);
        
    }

    const handleSave = (postId) => {
        updatePost(postId, updatedTitle, updatedBody);
        setIsEditing(false);
    };

    const handleClick = (postId) => {
        console.log(postId);
    }

    return (
        <article onClick={() => handleClick(post.id)} className="relative flex flex-col gap-2 border-9 border-black-1000 rounded-2xl bg-green-950 mt-6 w-96 h-auto p-4 overflow-hidden shadow-3xl text-black">
          {isEditing ? (
            <div>
              <input
                className='bg-transparent text-black border-b-2 rounded-sm border-black uppercase mb-4'
                type="text"
                value={updatedTitle}
                onChange={(e) => setUpdatedTitle(e.target.value)}
              />
              <textarea
                className='bg-transparent border-2 border-black p-2 text-black w-full h-auto overflow-hidden rounded-lg'
                value={updatedBody}
                onChange={(e) => setUpdatedBody(e.target.value)}
              />
              <button 
              className='border-9 rounded-xl border-black-1000 bg-blue-600 text-black p-2 shadow-2xl w-10 absolute top-2 right-16' 
              onClick={() => handleSave(post.id)}
              >
                <RiSave3Fill className='w-full h-full'/>
              </button>
              <button 
              className='border-9 rounded-xl border-black-1000 bg-red-700 text-black p-2 shadow-2xl w-10 absolute top-2 right-2'
              onClick={() => handleCancelEdit(post.id)}
              >
                <GiCancel/>
              </button>
            </div>
          ) : (
            <div>
              <h2 className="text-xl font-bold text-white uppercase">
                {post.id} {post.title}
              </h2>
              <p className="my-4 text-gray-950 ">{post.body}</p>
              <button 
              className='border-9 rounded-xl border-black-1000 bg-yellow-500 text-black p-2 shadow-2xl w-10 absolute bottom-2 right-2'
              onClick={() => handleEdit(post.id)} >
                <GrEdit/>
              </button>
            </div>
          )}
        </article>
      );
}

export default PostItem

I am using the App Router directory from NextJs 13.

tukitooo1998
  • 337
  • 10
  • 1
    You can't change the API response because its fixed but you need to add the response of API into your database then, implement PUT request on it (on your database.) – Kannu Mandora Jul 16 '23 at 04:12

0 Answers0