React实现点击左右箭头交换卡片数组元素顺序的问题排查
React卡片排序功能问题修复
现存问题汇总
- CardItem组件的事件绑定语法错误:未使用
this指向类方法,且直接调用函数而非传入函数引用,同时index、card变量未在当前作用域定义 - CardList传递给子组件的
index属性错误:遍历卡片数组时错误使用不存在的card.index,未传入数组实际下标 moveLeft逻辑缺陷:map遍历仅返回交换的两个卡片元素,其余位置元素无返回值会变为undefined- 边界判断错误:左移逻辑限制
index>1导致第2个卡片(下标1)无法左移,正确边界应为index>0 removeCard逻辑错误:直接修改原state,且filter判断条件错误,过滤逻辑完全不生效
修正后代码
CardList.js
import React from "react"; import CardItem from "./CardItem"; import CardForm from "./CardForm"; import './Card.css'; class CardList extends React.Component { constructor(props) { super(props); // 统一绑定方法 this.addCard = this.addCard.bind(this); this.removeCard = this.removeCard.bind(this); this.moveLeft = this.moveLeft.bind(this); this.moveRight = this.moveRight.bind(this); this.state = { cards: JSON.parse(localStorage.getItem(`cards`)) || [] }; } componentDidUpdate(prevProps, prevState) { // 只有卡片数组变化时才更新localStorage,避免不必要写入 if (prevState.cards !== this.state.cards) { localStorage.setItem(`cards`, JSON.stringify(this.state.cards)); } } render() { const cards = this.getCards(); const cardNodes = ( <div style={{ display: 'flex' }}>{cards}</div> ); return ( <div> <CardForm addCard={this.addCard} /> <div className="container"> <div className="card-collection"> {cardNodes} </div> </div> </div> ); } addCard(name) { const card = { name }; this.setState({ cards: [...this.state.cards, card] }); } removeCard(index) { this.setState(prevState => ({ // 过滤掉对应下标的元素,不修改原数组 cards: prevState.cards.filter((_, i) => i !== index) })) } moveLeft(index) { if (index <= 0) return; // 第一个元素无法左移,直接返回 this.setState(prevState => { const newCards = [...prevState.cards]; // 交换相邻元素 [newCards[index], newCards[index - 1]] = [newCards[index - 1], newCards[index]]; return { cards: newCards }; }); } moveRight(index) { if (index >= this.state.cards.length - 1) return; // 最后一个元素无法右移 this.setState(prevState => { const newCards = [...prevState.cards]; [newCards[index], newCards[index + 1]] = [newCards[index + 1], newCards[index]]; return { cards: newCards }; }); } getCards() { return this.state.cards.map((card, index) => { return ( <CardItem key={index} // 列表渲染必须加key card={card} index={index} // 传入数组实际下标 name={card.name} removeCard={this.removeCard} moveLeft={this.moveLeft} moveRight={this.moveRight} /> ); }); } } export default CardList;
CardItem.js
import React from 'react'; import Card from "react-bootstrap/Card"; import Button from "react-bootstrap/Button"; class CardItem extends React.Component { // 类方法统一绑定this,避免render里重复bind constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); this.leftClick = this.leftClick.bind(this); this.rightClick = this.rightClick.bind(this); } render() { return ( <div> <Card style={{ width: '15rem'}}> <Card.Header as="h5">{this.props.name}</Card.Header> <Card.Body> <Button variant="primary" onClick={this.handleClick}>Remove</Button> </Card.Body> <Card.Footer style={{ display: 'flex' }}> {/* 传入函数引用,点击时才执行,参数从props取 */} <i className="arrow left icon" onClick={this.leftClick} style={{ color: 'blue'}}></i> <i className="arrow right icon" onClick={this.rightClick} style={{ color: 'blue'}}></i> </Card.Footer> </Card> </div> ) } handleClick() { this.props.removeCard(this.props.index) } leftClick() { this.props.moveLeft(this.props.index) } rightClick() { this.props.moveRight(this.props.index) } } export default CardItem;
内容的提问来源于stack exchange,提问作者user16644688
相关产品推荐
相关产品推荐

