如何一次性重渲染父组件内的多个React组件?工单打乱问题求助
问题解答
关于useState能否传入多个参数
useState本身只能存储单个状态值,没法直接传入多个参数。但你现在用三个独立的useState分别管理三类工单的做法是完全没问题的,这不是导致打乱功能失效的原因。
打乱功能失效的核心原因及修复方案
你的代码里有三个关键问题导致功能不生效:
1. 原地修改原数组,React无法检测到状态变化
Array.sort()是原地排序方法,会直接修改原数组(比如notStartedTickets)。你把修改后的原数组传给setShuffledNewTickets时,数组的引用地址根本没变,React会认为状态没有更新,自然不会触发重渲染。
2. <option>的onClick事件兼容性差
大部分浏览器不会触发<option>上的onClick事件,应该把事件绑定到<select>的onChange事件上。
3. 随机排序的方式不够可靠
用Math.random() - 0.5作为排序依据的方式,随机性不稳定,推荐用更标准的Fisher-Yates洗牌算法来实现数组打乱。
修正后的完整代码
import React, { useState } from "react"; import styles from "./Tickets.module.css"; import TicketTable from "./TicketTable"; import Modal from "./Modal"; const Tickets = () => { // 原始工单数据(作为不可变的数据源) const notStartedTickets = [ { id: 1, assignee: "trevor strnad", time: "1h" }, { id: 9, assignee: "trevor strnad", time: "1h" }, { id: 10, assignee: "n8 feet under ", time: "1h" }, ]; const inProgressTickets = [ { id: 11, assignee: "n8 feet under ", time: "1h" }, { id: 12, assignee: "ryan knight", time: "1h" }, { id: 15, assignee: "trevor strnad", time: "1h" }, ]; const completedTickets = [ { id: 16, assignee: "n8 feet under ", time: "1h" }, { id: 17, assignee: "ryan knight", time: "1h" }, { id: 18, assignee: "trevor strnad", time: "1h" }, ]; const [shuffledNewTickets, setShuffledNewTickets] = useState(notStartedTickets); const [shuffledStartedTickets, setShuffledStartedTickets] = useState(inProgressTickets); const [shuffledDoneTickets, setShuffledDoneTickets] = useState(completedTickets); // Fisher-Yates 洗牌算法,返回新数组,不修改原数组 const shuffleArray = (array) => { const newArray = [...array]; for (let i = newArray.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [newArray[i], newArray[j]] = [newArray[j], newArray[i]]; } return newArray; }; const shuffleTickets = () => { // 传入洗牌后的新数组,确保引用变化 setShuffledNewTickets(shuffleArray(notStartedTickets)); setShuffledStartedTickets(shuffleArray(inProgressTickets)); setShuffledDoneTickets(shuffleArray(completedTickets)); }; // 补充代码里缺失的模态框相关状态和方法 const [createTicketModal, setCreateTicketModal] = useState(false); const [editTicketModal, setEditTicketModal] = useState(false); const toggleNewTicketModal = () => setCreateTicketModal(!createTicketModal); const toggleEditTicketModal = () => setEditTicketModal(!editTicketModal); const createTicket = () => { // 这里可添加创建工单的逻辑 toggleNewTicketModal(); }; return ( <> <div className={styles.create}> {/* 把事件绑定到select的onChange上 */} <select className={styles.projects} onChange={shuffleTickets}> <option value="project 1">Project 1</option> <option value="project 2">Project 2</option> <option value="project 3">Project 3</option> <option value="project 4">Project 4</option> </select> <button onClick={toggleNewTicketModal} className={styles.button}> create ticket </button> </div> <div className={styles.tickets}> {editTicketModal ? <Modal onToggleModal={toggleEditTicketModal} onCreateTicket={createTicket} title={'edit ticket'}/> : createTicketModal ? <Modal onToggleModal={toggleNewTicketModal} onCreateTicket={createTicket} title={'new ticket'} /> : null } <TicketTable color="red" header="not started" tickets={shuffledNewTickets} onToggleModal={toggleEditTicketModal} /> <TicketTable color="blue" header="in progress" tickets={shuffledStartedTickets} onToggleModal={toggleEditTicketModal} /> <TicketTable color="green" header="completed" tickets={shuffledDoneTickets} onToggleModal={toggleEditTicketModal} /> </div> </> ); }; export default Tickets;
内容的提问来源于stack exchange,提问作者gtrman97
相关产品推荐
相关产品推荐

