React实现带复选框的表格:提交时更新选中项目状态
Hey there! Let's walk through this solution step by step since you're new to React—no fancy jargon, just straightforward steps 😊
We'll cover two approaches: one matching your existing class component snippet, and a modern function component version (recommended for new React code). The core idea is tracking selected projects and updating their status without mutating your original data (a critical React rule!).
Class Component Approach (Matching Your Snippet)
Since your code uses this.submitClicked, let's start with a class-based solution that fits your existing setup:
1. Set Up Component State
First, we need to track two things: your list of projects, and the IDs of selected projects. Add this to your component:
class ProjectApprovalForm extends React.Component { // Initialize state with sample projects (replace with your actual data) state = { projects: [ { id: 1, name: "Website Redesign", status: "Pending Approval" }, { id: 2, name: "API Integration", status: "Pending Approval" }, { id: 3, name: "Mobile App Update", status: "Approved" } ], selectedProjectIds: [] // Tracks which projects are checked }; }
2. Handle Checkbox Selection
Add a method to update the selected IDs when a checkbox is toggled:
handleCheckboxChange = (projectId) => { this.setState(prevState => { // Check if the project is already selected const isSelected = prevState.selectedProjectIds.includes(projectId); return { selectedProjectIds: isSelected // If selected, remove it from the list ? prevState.selectedProjectIds.filter(id => id !== projectId) // If not selected, add it to the list : [...prevState.selectedProjectIds, projectId] }; }); };
3. Render the Table with Checkboxes
Update your table to render each project row with a linked checkbox:
render() { return ( <Form onSubmit={this.submitClicked}> {/* Use form's onSubmit instead of button onClick for better semantics */} <FormGroup> <Button type="submit">Approve Projects</Button> </FormGroup> <table> <thead> <tr> <th>Select</th> <th>Project Name</th> <th>Status</th> </tr> </thead> <tbody> {this.state.projects.map(project => ( <tr key={project.id}> {/* Always use a unique key for list items */} <td> <input type="checkbox" checked={this.state.selectedProjectIds.includes(project.id)} onChange={() => this.handleCheckboxChange(project.id)} /> </td> <td>{project.name}</td> <td>{project.status}</td> </tr> ))} </tbody> </table> </Form> ); }
4. Handle Form Submission
Finally, add your submitClicked method to update the status of selected projects:
submitClicked = (e) => { e.preventDefault(); // Prevent default form refresh (critical for React apps!) // Update the projects' status this.setState(prevState => { const updatedProjects = prevState.projects.map(project => { // If project is selected, change status to Approved if (prevState.selectedProjectIds.includes(project.id)) { return { ...project, status: "Approved" }; // Don't mutate the original object! } return project; // Leave unselected projects as-is }); return { projects: updatedProjects, selectedProjectIds: [] // Clear selected checkboxes after submission }; }); // Optional: Send selected IDs to your backend (example with fetch) // fetch('/api/approve-projects', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify({ projectIds: this.state.selectedProjectIds }) // }); };
Modern Function Component Approach (Recommended)
If you're open to using modern React hooks, here's a cleaner version with useState:
import { useState } from 'react'; import { Form, FormGroup, Button } from 'your-ui-library'; // Adjust to your actual UI library function ProjectApprovalForm() { const [projects, setProjects] = useState([ { id: 1, name: "Website Redesign", status: "Pending Approval" }, { id: 2, name: "API Integration", status: "Pending Approval" }, { id: 3, name: "Mobile App Update", status: "Approved" } ]); const [selectedProjectIds, setSelectedProjectIds] = useState([]); const handleCheckboxChange = (projectId) => { setSelectedProjectIds(prev => { const isSelected = prev.includes(projectId); return isSelected ? prev.filter(id => id !== projectId) : [...prev, projectId]; }); }; const submitClicked = (e) => { e.preventDefault(); // Update project statuses setProjects(prev => prev.map(project => selectedProjectIds.includes(project.id) ? { ...project, status: "Approved" } : project )); setSelectedProjectIds([]); // Clear selections // Add backend API call here if needed }; return ( <Form onSubmit={submitClicked}> <FormGroup> <Button type="submit">Approve Projects</Button> </FormGroup> <table> <thead> <tr> <th>Select</th> <th>Project Name</th> <th>Status</th> </tr> </thead> <tbody> {projects.map(project => ( <tr key={project.id}> <td> <input type="checkbox" checked={selectedProjectIds.includes(project.id)} onChange={() => handleCheckboxChange(project.id)} /> </td> <td>{project.name}</td> <td>{project.status}</td> </tr> ))} </tbody> </table> </Form> ); }
Key Notes to Remember
- Never mutate state directly: Always create new objects/arrays when updating state (that's why we use
...spreadandmap/filter). - Unique keys: Always use a unique identifier (like
project.id) for list items, not array indexes. - Prevent default form behavior: Use
e.preventDefault()in your submit handler to stop the browser from refreshing the page.
内容的提问来源于stack exchange,提问作者User9123

