如何按组件点击顺序而非标识符排序数组?React开发咨询
解决方案:追踪点击顺序并据此排序组件数组
你的核心问题在于:当前arrMiniDices是直接遍历原listDices数组生成的,严格遵循原数组的id顺序,完全没考虑用户的点击行为。要实现按点击顺序排列,关键是先记录用户的点击顺序,再根据这个顺序来排序生成组件的数组。
下面是具体的分步解决方案:
1. 维护一个记录点击顺序的状态
首先在组件中添加状态,专门存储用户点击骰子的id顺序。
类组件示例:
class YourComponent extends React.Component { constructor(props) { super(props); this.state = { listDices: [ {value: 1, hidden: false, id:0}, {value: 2, hidden: false, id:1}, {value: 6, hidden: false, id:2}, {value: 6, hidden: false, id:3}, {value: 5, hidden: false, id:4} ], clickedOrder: [] // 存储点击的id顺序 }; } // 其他方法... }
函数组件示例:
const YourComponent = () => { const [listDices, setListDices] = useState([ {value: 1, hidden: false, id:0}, {value: 2, hidden: false, id:1}, {value: 6, hidden: false, id:2}, {value: 6, hidden: false, id:3}, {value: 5, hidden: false, id:4} ]); const [clickedOrder, setClickedOrder] = useState([]); // 其他逻辑... };
2. 更新点击事件处理函数,维护点击顺序
修改handleHideDice方法,在切换骰子hidden状态的同时,同步更新点击顺序:
- 当骰子从显示切换为隐藏(加入
arrMiniDices):如果该id已在顺序中,先移除再追加到末尾(保证最新点击的排在最后);如果不在,直接追加。 - 当骰子从隐藏切换为显示(移出
arrMiniDices):从顺序中移除对应id。
类组件示例:
handleHideDice = (id) => { // 先更新骰子的hidden状态 this.setState(prevState => ({ listDices: prevState.listDices.map(item => item.id === id ? {...item, hidden: !item.hidden} : item ) }), () => { // 状态更新完成后处理点击顺序 const targetDice = this.state.listDices.find(item => item.id === id); this.setState(prevState => { let newClickedOrder = [...prevState.clickedOrder]; if (targetDice.hidden) { // 隐藏状态:移到顺序末尾或新增 const existingIndex = newClickedOrder.indexOf(id); if (existingIndex !== -1) newClickedOrder.splice(existingIndex, 1); newClickedOrder.push(id); } else { // 显示状态:从顺序中移除 const existingIndex = newClickedOrder.indexOf(id); if (existingIndex !== -1) newClickedOrder.splice(existingIndex, 1); } return { clickedOrder: newClickedOrder }; }); }); };
函数组件示例(结合useEffect处理异步状态):
const handleHideDice = (id) => { setListDices(prev => prev.map(item => item.id === id ? {...item, hidden: !item.hidden} : item )); }; // 监听listDices变化,同步更新点击顺序 useEffect(() => { const updatedDice = listDices.find(item => item.id === id); if (!updatedDice) return; setClickedOrder(prev => { let newOrder = [...prev]; if (updatedDice.hidden) { const idx = newOrder.indexOf(updatedDice.id); if (idx !== -1) newOrder.splice(idx, 1); newOrder.push(updatedDice.id); } else { const idx = newOrder.indexOf(updatedDice.id); if (idx !== -1) newOrder.splice(idx, 1); } return newOrder; }); }, [listDices, id]);
3. 根据点击顺序生成arrMiniDices
不再直接遍历原数组,先过滤出hidden为true的骰子,再根据clickedOrder的顺序排序,最后生成组件:
// 类组件中 const { listDices, clickedOrder } = this.state; const hiddenDices = listDices.filter(item => item.hidden); const arrMiniDices = hiddenDices.sort((a, b) => { // 按clickedOrder中的索引排序,索引越小越靠前 return clickedOrder.indexOf(a.id) - clickedOrder.indexOf(b.id); }).map(item => ( <BtnDice key={item.id} value={item.value} className="btn__dice--small" onClick={() => this.handleHideDice(item.id)} /> )); // 函数组件逻辑完全一致,仅需替换为对应状态和方法
4. 初始化点击顺序(可选)
如果初始listDices中有已隐藏的骰子,需要在组件挂载时初始化clickedOrder,保证这些初始项按原顺序排列:
类组件:
componentDidMount() { const initialOrder = this.state.listDices .filter(item => item.hidden) .map(item => item.id); this.setState({ clickedOrder: initialOrder }); }
函数组件:
useEffect(() => { const initialOrder = listDices.filter(item => item.hidden).map(item => item.id); setClickedOrder(initialOrder); }, []);
这样调整后,当你按d(id3) → b(id1) → c(id2) → a(id0) → e(id4)的顺序点击时,arrMiniDices就会严格按照这个点击顺序生成组件数组,完全符合你的预期。
内容的提问来源于stack exchange,提问作者yoan
相关产品推荐
相关产品推荐

