0

Good evening, I have an object that I am sending a PUT to my API to update book information. I want to be able to only send one property to the API and have the rest persist. As of right now they are set to undefined if you only set one property, you have to update all 3 for it to work. The below code is the re-usable component, this component is made for every book that is stored in the API.

Book.js

import React, { useState } from "react";
import {
    deleteBook,
    updateBook
  } from '../api/books';

// Material UI
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
import Stack from '@mui/material/Stack';

const Book = ({setBooks, bookId, bookTitle, bookStart, bookEnd}) => {

    // State to update an existing books data
  const [updateNewBookTitle, setNewUpdateBookTitle] = useState("");
  const [updateNewBookStart, setNewUpdateBookStart] = useState("");
  const [updateNewBookEnd, setNewUpdateBookEnd] = useState("");

    // Delete a specific book
    const onDeleteBook = async (id) => {
        const responseStatus = await deleteBook(id);
    
        if (responseStatus !== 200) {
          alert("Deleting failed");
          return;
        }
    
        setBooks((previousBooks) =>
          previousBooks.filter((book) => book.id !== id)
        );
      };
    
      // Update a previous book
      const onUpdateBook = async (id, newTitle, newStart, newEnd) => {
        const responseStatus = await updateBook(id, newTitle, newStart, newEnd);
    
        if (responseStatus !== 200) {
          alert("Updating failed");
          return;
        }
    
        setBooks((previousBooks) => {
          const nextBooksState = [...previousBooks];
          const bookToUpdate = nextBooksState.find(
            (book) => book.id === id
          );
    
          bookToUpdate.title = newTitle;
          bookToUpdate.start = newStart;
          bookToUpdate.end = newEnd;


         
    
          return nextBooksState;
        });
      };
    
    return (
        <form onSubmit={() => {onUpdateBook(bookId, updateNewBookTitle, updateNewBookStart, updateNewBookEnd)}}>
          <Stack key={bookId}>
          <TextField id="standard-basic"
                     label="Title"
                     defaultValue={bookTitle}
                     variant="standard"
                     onChange={e => setNewUpdateBookTitle(e.target.value)}
          />
          <TextField id="standard-basic"
                     label="Start Date"
                     defaultValue={bookStart}
                     variant="standard"
                     onChange={e => setNewUpdateBookStart(e.target.value)}
          />
          <TextField id="standard-basic"
                     label="End Date"
                     defaultValue={bookEnd}
                     variant="standard"
                     onChange={e => setNewUpdateBookEnd(e.target.value)}
          />
          <Button variant="contained"
                  color="success"
                  type="submit"
          >
            Update Book
          </Button>
          <Button variant="contained"
                  color="error"
                  onClick={() => {onDeleteBook(bookId)}}
          >
            Delete Book
          </Button>
        </Stack>
        </form>
        
      )
}
export default Book;

1 Answer 1

2

Updating the database will be directly related to your backend function. Because you want to send only one property or lets say not the entire object with full info, so your server PUT request should handle that part. I think there can be 2 options to achieve what you want:

  1. Retrieve all book information into the component and make a PUT request with existing&updated data in the same object.
  2. Send only the updated information to your server function and add a if/switch or any other condition case which checks if your request object contains full data columns in database. if it's false, then you still fetch the relevant book data, use spread operator and only update the relevant key. Like: requestObject = { ...existingBookData, updatedData}

I hope it makes sense

Sign up to request clarification or add additional context in comments.

2 Comments

That actually does make since, I am wanting to use your second solution. Would you be able share some pseudo code?
Sure, I haven't done the exact same thing you need but you can have a look at this example(I used express): router.post("/:id", async (req, res, next) => { try { const bookID = parseFloat(req.params.id); const bookToBeUpdated = await Books.findByPk(bookID); const bookUpdated = await bookToBeUpdated.update(req.body); //this part updates your particular book, you can add the conditions you want to check before you update and it would work I guess res.json(bookUpdated); next(); } catch (error) { console.log(error.message); next(error); } });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.