【问题标题】:Clicking a left arrow or a right arrow to switch an element in an array with the element on the left or right React单击左箭头或右箭头以切换数组中的元素与左侧或右侧的元素 React
【发布时间】:2021-11-11 17:33:03
【问题描述】:

我是 React 的新手,我正在尝试构建一个应用程序,用户可以在其中创建卡片、删除卡片,并通过单击左箭头或右箭头来更改卡片数组的顺序,以切换元素与左边或右边。 我正在努力编写这个功能。我已经编写了将卡与左侧的卡进行切换的功能,但是该功能现在没有做任何事情。我也没有从这个函数的控制台中得到任何错误,所以我真的无法确定我哪里出错了。 到目前为止的代码如下:

CardList.js 将显示添加卡片的表单并显示 CardItems 数组,将这些项目向左或向右切换的函数('moveLeft','moveRight')作为道具传递。

import React from "react";
import CardItem from "./CardItem";
import CardForm from "./CardForm";
import './Card.css';

class CardList extends React.Component {
  state = {
    cards: JSON.parse(localStorage.getItem(`cards`)) || []
    // when the component mounts, read from localStorage and set/initialize the state
  };

  componentDidUpdate(prevProps, prevState) { // persist state changes to longer term storage when it's updated
      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.bind(this)} /> 
     <div className="container">
     <div className="card-collection">
          {cardNodes} 
          </div>
      </div>
      </div>
    );
  }

  addCard(name) {
    const card = {
      name
    };
    this.setState({
      cards: this.state.cards.concat([card])
    }); // new array references help React stay fast, so concat works better than push here.
  }
  
  
  removeCard(index) {
    this.state.cards.splice(index, 1)
    this.setState({
      cards: this.state.cards.filter(i => i !== index)
    })
  }

  moveLeft(index,card) {
   if (index > 1) {
     this.state.cards.splice(index, 1);
     this.state.cards.splice((index !== 0) ? index - 1 : this.state.cards.length, 0, card)
   }
    return this.state.cards
 }

  moveRight(index, card) {
   // ?
  }

  getCards() {
    return this.state.cards.map((card) => {
      return (
        <CardItem
          card={card}
          index={card.index}
          name={card.name}
          removeCard={this.removeCard.bind(this)}
          moveLeft={this.moveLeft.bind(this)}
          moveRight={this.moveRight.bind(this)}
        />
      );
    });
  }
}
export default CardList;

CardItem 正在接受这些道具,并在理想情况下处理单击左或右图标后在数组中向左或向右移动卡片。

import React from 'react';

import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";

class CardItem extends React.Component {
 render() {
  return (
  <div>
 <Card style={{ width: '15rem'}}>
  <Card.Header as="h5">{this.props.name}</Card.Header>
  <Card.Body>
    <Button variant="primary" onClick={this.handleClick.bind(this)}>Remove</Button>
  </Card.Body>
  <Card.Footer style={{ display: 'flex' }}>
  <i class="arrow left icon" onClick={this.leftClick.bind(this)} style={{ color: 'blue'}}></i>
  <i class="arrow right icon" onClick={this.rightClick.bind(this)} style={{ color: 'blue'}}></i>
  </Card.Footer>
</Card>
 </div>
    )
  }

handleClick(index) { 
  this.props.removeCard(index)
}

leftClick(index, card) {
this.props.moveLeft(index, card)
}

rightClick(index, card) {
  this.props.moveRight(index, card)
}

}
export default CardItem;

不知道我在哪里出错了。任何帮助将不胜感激

编辑#1 嘿伙计们,所以我写了一个不同的函数来处理向左移动卡片,我决定将“this”绑定到构造函数中的那个方法,因为我收到错误说程序无法读取它。但是,我仍然收到错误,基本上说当我将函数从 CardList 传递给 CardItem 作为道具时,一切都没有定义。有谁知道问题是什么?当我调用 CardItem 中的方法时,我怀疑它是我的语法。

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();

    this.moveLeft = this.moveLeft.bind(this);
    this.moveRight = this.moveRight.bind(this);
    this.state = {
      cards: JSON.parse(localStorage.getItem(`cards`)) || []
      // when the component mounts, read from localStorage and set/initialize the state
    };
  }
  
  

  componentDidUpdate(prevProps, prevState) { // persist state changes to longer term storage when it's updated
      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.bind(this)} /> 
     <div className="container">
     <div className="card-collection">
          {cardNodes} 
          </div>
      </div>
      </div>
    );
  }

  addCard(name) {
    const card = {
      name
    };
    this.setState({
      cards: this.state.cards.concat([card])
    }); // new array references help React stay fast, so concat works better than push here.
  }
  
  
  removeCard(index) {
    this.state.cards.splice(index, 1)
    this.setState({
      cards: this.state.cards.filter(i => i !== index)
    })
  }

  moveLeft(index, card) {
    this.setState((prevState, prevProps) => {
        return {cards: prevState.cards.map(( c, i)=> {
            // also handle case when index == 0
            if (i === index) {
                return prevState.cards[index - 1];
            } else if (i === index - 1) {
                return prevState.cards[index];
            }    
        })};
    }); 
 }

  moveRight(index, card) {
   // ?
  }

  getCards() {
    return this.state.cards.map((card) => {
      return (
        <CardItem
          card={card}
          index={card.index}
          name={card.name}
          removeCard={this.removeCard.bind(this)}
          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 {
 render() {
  return (
  <div>
 <Card style={{ width: '15rem'}}>
  <Card.Header as="h5">{this.props.name}</Card.Header>
  <Card.Body>
    <Button variant="primary" onClick={this.handleClick.bind(this)}>Remove</Button>
  </Card.Body>
  <Card.Footer style={{ display: 'flex' }}>
  <i class="arrow left icon" onClick={leftClick(index, card)} style={{ color: 'blue'}}></i>
  <i class="arrow right icon" onClick={rightClick(index, card)} style={{ color: 'blue'}}></i>
  </Card.Footer>
</Card>
 </div>
    )
  }

handleClick(index) { 
  this.props.removeCard(index)
}

leftClick(index, card) {
this.props.moveLeft(index,card)
}

rightClick(index, card) {
  this.props.moveRight(index, card)
}

}
export default CardItem;

【问题讨论】:

    标签: javascript html arrays reactjs event-handling


    【解决方案1】:

    要在 React 中更新状态数组,您不应使用 splicepush[] 运算符。

    改为使用返回新数组对象的方法,即。 map, filter, concat,slice.

    详细解释见article

    所以你可以这样做:

    moveLeft(index,card) {
        this.setState((prevState, prevProps)=> {
            return {cards: prevState.cards.map((c,i)=> {
                // also handle case when index == 0
                if(i == index) {
                    return prevState.cards[index-1];
                } else if(i == index-1) {
                    return prevState.cards[index];
                }    
            })};
        }); 
     }
    

    当使用之前的值更新 React 状态时,总是使用

    setState((prevState,prevProps)=>{ return ...})
    

    因此,状态更新可能是异步的。 See React docs.

    由于是从子组件调用父组件方法,最好在CardList构造函数中绑定这些方法。例如:

    this.moveLeft = this.moveLeft.bind(this);
    this.moveRight ....
    

    【讨论】:

    • 我明白了。谢谢,有道理。但是由于某种原因仍然对我不起作用,当我单击左箭头时,我现在收到一条错误消息,提示“TypeError:无法读取未定义的属性“索引”……不知道为什么会发生这种情况。传入索引和卡片作为道具和参数
    • 我认为这与“this”关键字的值有关,因为该方法是从子组件调用的。请参阅有关绑定的编辑。
    • 非常感谢您的帮助。这种绑定对我来说是新的......所以我在我的构造函数中绑定了它,然后像这样从 cardList 传递道具:moveLeft={this.moveLeft} moveRight={this.moveRight}
    • cardItem在使用这些函数的时候,可以在表单中这样调用吗? ` leftClick(index, card) { moveLeft(index, card) }
    • 当我写到我仍然收到错误
    猜你喜欢
    • 2019-02-24
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多