Refs возвращаются как ноль - PullRequest
       38

Refs возвращаются как ноль

0 голосов
/ 26 сентября 2019

У меня есть массив «выбранных карт», сохраненный в состоянии «selectedCards», который обновляется в зависимости от того, ссылался ли пользователь на идентификатор «Карты» или нет (с помощью флажка).

КогдаКомпонент монтируется, массив по умолчанию сопоставляется с использованием компонента «Карта» и добавляется в стек.Доступ к ним осуществляется с помощью ссылок и с использованием взаимодействия в стиле трутов, пользователи могут выбрасывать влево или вправо с помощью клавиатуры или перетаскивания из стека.

Когда компонент обновляется и добавляет новые карты в стек, ссылки становятсявернулся как ноль.Почему это так?

export default class Cards extends Component {
  constructor(props, context) {
    super(props, context);
    this.config = {
      throwOutDistance: () => Math.max(window.innerWidth, window.innerHeight),
      throwOutConfidence: () => 1,
      allowedDirections: [
        Direction.LEFT,
        Direction.RIGHT,
      ]
    };

    const fakeEvent = {
      target: {
        id: 'digiDesign',
      }
    };

    this.cardRefs = new Map();

    this.state = {
      selectedCategories: ['digiDesign', 'branding'],
      selectedCards: this.filterArray(fakeEvent),
      cardStack: cardData,
      currentCard: cardData.length - 1,
      cardIndex: 0,
      checked: false,
    };
  }

  componentDidMount() {
    const { selectedCards } = this.state;

    //Intiates key listener
    document.addEventListener("keydown", this.onDirection);

    //Configures Swing.js
    this.stack = Stack(this.config);
    this.stack.on("dragstart", () => this.setState({ dragging: true }));
    this.stack.on("dragend", () => this.setState({ dragging: false }));
    this.stack.on("throwout", this.onThrowOut.bind(this));

    //Config stack of cards
    this.createStack();

    //Logs initial cards
    console.log(selectedCards, 'selected cards')
  }

  handleChange(e){
    const { selectedCards } = this.state;

    if (e.target.checked){
      for (let i = 0; i < this.filterArray(e).length; i++){
        selectedCards.push(this.filterArray(e)[i])
      }
    } if (!e.target.checked){
      this.removeArray(e);
    }

    this.setState({
      selectedCards
    })

    console.log(selectedCards)
  }

  createStack(){
    const { selectedCards } = this.state;
    this.cardRefs.forEach((ref) => {
      const el = ReactDOM.findDOMNode(ref);
      this.stack.createCard(el);
  });

    this.setState({
      currentCard: selectedCards.length - 1
    })
  }

  destroyStack(){
    this.cardRefs.forEach((ref) => {
      const el = ReactDOM.findDOMNode(ref);
      const card = this.stack.getCard(el);
      card.destroy();
    });
  }

  componentWillUnmount() {
    this.destroyStack()
  }

  //Controls keycodes
  onDirection = e => {
    if(e.keyCode === 37){
      this.throwoutLeft();
    } if (e.keyCode === 39) {
      this.throwoutRight();
    }
  }

  //Controls throwout right with key
  throwoutRight(){
    const el = ReactDOM.findDOMNode(
      this.cardRefs.get(this.state.currentCard)
    );
    const card = this.stack.getCard(el);
    card.throwOut(1000, 0);
  }

  //Controls throwout left with key
  throwoutLeft(){
    const el = ReactDOM.findDOMNode(
      this.cardRefs.get(this.state.currentCard)
    );
    const card = this.stack.getCard(el);
    card.throwOut(-1000, 0);
  }

  //Controls swipe/grab
  onThrowOut() {
    const activeCard = this.state.currentCard

    if (activeCard > 0){
      this.setState({
        currentCard: activeCard - 1
      })
    }

    if (activeCard === 0){
      this.setState({
        currentCard: activeCard - 1
      })
      this.resetDeck();
    }
  }

  //Resets the deck on finish
  resetDeck() {
    const { selectedCards } = this.state


    this.setState({
      currentCard:selectedCards.length - 1,
      resetting: true
    });

    this.createStack()

    this.setState({
      resetting: false,
    });
  }

 //Controls checkboxes
  filterArray(e){
    let filteredArray = cardData.filter(function(x){
      return x.id === e.target.id
    });
    return filteredArray
  }

  removeArray(e){
    const{ selectedCards } = this.state;
    for (let i = selectedCards.length-1; i >= 0; i--){
      if(selectedCards[i].id === e.target.id){
        selectedCards.splice(i, 1)
      }
    }
  }

  render() {
    const { selectedCards } = this.state;
    return (
      <div className='container'>
      <Viewport>
        <CardStack className='stack'>
          {selectedCards.map((card, i) => {
            return (
              <Card
                selectedCategories={this.state.selectedCategories}
                key={card.advice}
                ref={c => this.cardRefs.set(i, c)}
                advice={card.advice}
                id={card.id}
                tag={card.tag}
                isSelected={this.state.selectedCategories.indexOf(card.id) > -1}
                active={i === this.state.currentCard}
                next={i === this.state.currentCard - 1}
                previous={i > this.state.currentCard}
                dragging={
                  (i === this.state.currentCard && this.state.dragging) ||
                  this.state.resetting
                }
              />
            )
          })}
        </CardStack>
        <FilterContainer>
          {
            filterData.map((item, i) => {

              const active = i === 0;
              return (
                <Filters
                  ref='input'
                  key={item.id}
                  id={item.id}
                  label={item.label}
                  onChange={(e) => this.handleChange(e)}
                  active={active}
                />
              )
            })
          }
        </FilterContainer>
      </Viewport>
      </div>
    );
  }
}

Ожидаемый результат - новые карты получат функцию throwIn, но, если новые реферы возвращаются как ноль, этого достичь нельзя.

1 Ответ

0 голосов
/ 26 сентября 2019

Так как вы используете карту, итерацию массива для хранения ваших ссылок.Вам придется преобразовать карту обратно в массив, прежде чем вы сможете использовать такие методы, как forEach.

  createStack(){
    const { selectedCards } = this.state;
    let allRefs = Array.from(this.refs.values())
    allRefs.forEach((ref) => {
      const el = ReactDOM.findDOMNode(ref);
      this.stack.createCard(el);
    });

    this.setState({
      currentCard: selectedCards.length - 1
    })
  }

  destroyStack(){
    let allRefs = Array.from(this.refs.values())
    allRefs.forEach((ref) => {
      const el = ReactDOM.findDOMNode(ref);
      const card = this.stack.getCard(el);
      card.destroy();
    });
  }

Надеюсь, это поможет!

...