You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中为Checkbox设置onChange及解决刷新后状态丢失问题

解决Checkbox刷新后状态重置的问题

你的问题根源在于初始状态未从后端获取真实值,且组件的状态管理和后端更新逻辑脱节,具体修正步骤如下:

1. 从Props传入真实的已读状态

组件初始化时useState(false)硬编码为未选中,刷新后自然回到初始值。需要让父组件把书籍的finished状态作为props传入:

// 修改组件接收的props,添加finished
const Book = ( {title, author, id, getBooks, finished}) => {
  // 用传入的finished作为初始state
  const [isFinished, setIsFinished] = useState(finished)

2. 把Checkbox改成受控组件

用checked替代defaultChecked,确保UI状态始终和本地state同步:

<input
  type="checkbox"
  name="finished"
  // 替换defaultChecked为checked
  checked={isFinished}
  className="form-check-input"
  onChange={handleCheckboxChange}
/>

3. 同步更新本地状态和后端数据

单独处理Checkbox的change事件,既要更新本地state,也要调用API修改后端数据,最后刷新书籍列表:

const handleCheckboxChange = async () => {
  const newStatus = !isFinished
  // 先更新本地状态,让UI即时反馈
  setIsFinished(newStatus)
  // 调用后端API更新数据
  try {
    await axios.put(`http://localhost:3000/api/v1/books/${id}`, {
      book: {
        finished: newStatus
      },
    })
    // 更新成功后调用getBooks刷新列表,确保数据一致
    getBooks()
  } catch (err) {
    // 失败时回滚状态
    setIsFinished(isFinished)
    console.error('更新失败', err)
  }
}

4. 修正文本输入框的更新逻辑

原来的handleChange会错误地把finished设为!isFinished(不管当前操作的是文本框还是Checkbox),需要移除这个错误逻辑,只更新对应输入框的字段:

const handleChange = async (e) => {
  const { name, value } = e.target;
  await axios.put(`http://localhost:3000/api/v1/books/${id}`, {
    book: {
      [name]: value,
      // 移除错误的finished: !isFinished
    },
  })
  getBooks()
}

完整修正后的代码

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

const Book = ( {title, author, id, getBooks, finished}) => {
  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,
      },
    })
    getBooks()
  };

  const handleCheckboxChange = async () => {
    const newStatus = !isFinished
    setIsFinished(newStatus)
    try {
      await axios.put(`http://localhost:3000/api/v1/books/${id}`, {
        book: {
          finished: newStatus
        },
      })
      getBooks()
    } catch (err) {
      setIsFinished(isFinished)
      console.error('更新已读状态失败', err)
    }
  }

  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"
            checked={isFinished}
            className="form-check-input"
            onChange={handleCheckboxChange}
          />
          <label className="form-check-label">
            Done
          </label>
        </div>
      </td>
    </tr>
  )
}

export default Book

额外注意

确保父组件在渲染Book时,把书籍对象的finished属性传递给子组件,比如:

// 父组件中渲染Book的示例
{books.map(book => (
  <Book
    key={book.id}
    title={book.title}
    author={book.author}
    id={book.id}
    finished={book.finished}
    getBooks={getBooks}
  />
))}

内容的提问来源于stack exchange,提问作者AndresM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 17:35:06