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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 23:57:00