0

I'm trying to update a record by selecting a checkbox when a book has been read. Whenever I refresh the page, the checkbox returns as unchecked. How can I store the selected checkbox and see it checked after the page is refreshed?

import React, { useState } from 'react';
import axios from 'axios';

const Book = ( {title, author, id, getBooks}) => {
  const [finished, setFinished] = useState(false)

  const handleChange = async (e) => {
    const { name, value } = e.target;

    await axios.put(`http://localhost:3000/api/v1/books/${id}`, {
        book: {
          [name]: value,
          finished: !finished
        },
      })
  };

  return (
    <tr>
      <td>
        <input
          type="text"
          name="title"
          defaultValue={title}
          onChange={handleChange}
          className="form-control"
        />
      </td>
      <td>
        <input
          type="text"
          name="author"
          defaultValue={author}
          onChange={handleChange}
          className="form-control"
        />
      </td>
      <td className="text-center">
        <div className="form-check form-check-inline pt-2">
          <input
            type="checkbox"
            name="finished"
            defaultChecked={finished}
            className="form-check-input"
            onChange={() => setFinished(!finished)}
          />
          <label className="form-check-label">
            Done
          </label>
        </div>
      </td>
    </tr>
  )
}

export default Book
obzva
  • 78
  • 6
AndresM
  • 61
  • 3
  • Does this answer your question? [Persist variables between page loads](https://stackoverflow.com/questions/29986657/persist-variables-between-page-loads) – Andy Ray May 24 '23 at 03:33
  • You probably want to use `value={title}` instead of `defaultValue`. – twharmon May 24 '23 at 04:33

1 Answers1

1

By looking at this component, I assume you are fetching the list of Books from the parent and I also assume that you have finished property from the book list data that you've fetch as well. You can pass that finished property to this component and set it as initial value to your finished state.

Sample on you do it

import React, { useState } from 'react';
import axios from 'axios';

const Book = ( {title, author, id, finished, getBooks}) => {
  const [isFinished, setIsFinished] = useState(finished)

  const handleChange = async (e) => {
    const { name, value } = e.target;

    await axios.put(`http://localhost:3000/api/v1/books/${id}`, {
        book: {
          [name]: value,
          finished: !isFinished
        },
      })
  };

  return (
    <tr>
      <td>
        <input
          type="text"
          name="title"
          defaultValue={title}
          onChange={handleChange}
          className="form-control"
        />
      </td>
      <td>
        <input
          type="text"
          name="author"
          defaultValue={author}
          onChange={handleChange}
          className="form-control"
        />
      </td>
      <td className="text-center">
        <div className="form-check form-check-inline pt-2">
          <input
            type="checkbox"
            name="finished"
            defaultChecked={isFinished}
            className="form-check-input"
            onChange={() => setIsFinished(!isFinished)}
          />
          <label className="form-check-label">
            Done
          </label>
        </div>
      </td>
    </tr>
  )
}

export default Book

Additional notes:

I changed your state name into isFinished to avoid same name error with your new props.

Also, if you want to be sure to save the checkbox change during checking/unchecking, you also need to listen to the changes on isFinished state using useEffect and save it again using your axios call.

Honestly tho, what you have right now is a very bad design. Don't spam api calls every change on your input. Use debounce or something. Just dont api call every change.

JkAlombro
  • 1,696
  • 1
  • 16
  • 30