Как использовать forEach в react js

#javascript #html #css #reactjs

Вопрос:

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

Это можно было бы легко сделать с помощью JavaScript.

 const boxes = document.querySelectorAll(".box1");
function remove_all_active_list() {
    boxes.forEach((element) => element.classList.remove('active'));
}
 

Но как я могу сделать эту похожую вещь, как я реагирую. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу использовать document.querySelectorAll(".box1") в React, но я могу использовать React.createRef() , но это дает мне не все элементы, а только последний элемент.

Это мой код реакции

App.js

 import React, { Component } from 'react';
import List from './List';

export class App extends Component {

    componentDidMount() {
        window.addEventListener('keydown', this.keypressed);
    }

    keypressed = (e) => {
        if (e.keyCode == '38' || e.keyCode == '40') this.remove_all_active_list();
    };

    remove_all_active_list = () => {
        // boxes.forEach((element) => element.classList.remove('active'));
    };

    divElement = (el) => {
        console.log(el);
        el.forEach((element) => element.classList.add('active'))
    };

    render() {
        return (
            <div className="container0">
                <List divElement={this.divElement} />
            </div>
        );
    }
}

export default App;

 

List.js

 import React, { Component } from 'react';
import data from './content/data';

export class List extends Component {
    divRef = React.createRef();

    componentDidMount() {
        this.props.divElement(this.divRef)
    }

    render() {
        let listItem = data.map(({ title, src }, i) => {
            return (
                <div className="box1" id={i} ref={this.divRef} key={src}>
                    <img src={src} title={title} align="center" alt={title} />
                    <span>{title}</span>
                </div>
            );
        });
        return <div className="container1">{listItem}</div>;
    }
}

export default List;
 

Пожалуйста, скажите мне, как я могу решить эту проблему.

Ответ №1:

Короткий ответ

Ты бы не стал.

Вместо этого вы бы условно добавили и удалили класс в элемент, компонент или collection.map() внутри вашего компонента React вместо этого.

Пример

Вот пример, который иллюстрирует оба:

 import styles from './Example.module.css';

const Example = () => {
  const myCondition = true;

  const myCollection = [1, 2, 3];

  return (
    <div>
      <div className={myCondition ? 'someGlobalClassName' : undefined}>Single element</div>
      {myCollection.map((member) => (
        <div key={member} className={myCondition ? styles.variant1 : styles.variant2}>
          {member}
        </div>
      ))}
    </div>
  );
};

export default Example;
 

Так что в вашем случае:

  • Вы можете передать active prop <ListItem /> компоненту и использовать props.active его в качестве условия.
  • В качестве альтернативы вы можете отправить activeIndex в <List /> компонент и использовать index === activeIndex в качестве условия на своей карте.

Объяснение

Вместо добавления или удаления классов в элемент HTMLElement react заботится о визуализации и обновлении всего элемента и всех его свойств (включая class — которые в react вы бы написали как className ).

Не вдаваясь в тень дома и почему реакция может быть предпочтительнее, я просто попытаюсь объяснить изменение в мышлении:

Компоненты не только описывают элементы html, но также могут содержать логику и поведение. Каждый раз, когда какое-либо свойство изменяется, по крайней мере, метод визуализации вызывается снова, и элемент заменяется новым элементом (т. е. Раньше без какого-либо класса, но теперь с классом).

Теперь гораздо проще менять классы. Все, что вам нужно сделать, это изменить свойство или изменить результат условия (оператор if).

Таким образом, вместо того, чтобы выбирать некоторые элементы в dom и применять к ним некоторую логику, вы вообще не будете выбирать какой-либо элемент; логика записана прямо внутри компонента react, рядом с той частью, которая выполняет фактический рендеринг.

Дальнейшее чтение

https://reactjs.org/docs/state-and-lifecycle.html

Пожалуйста, не стесняйтесь добавлять комментарий, если что-то нужно перефразировать или добавить.

Комментарии:

1. не могли бы вы, пожалуйста, объяснить это подробнее, я не понял

2. @ArpitFalcon Я добавил объяснение своими словами, пытаясь объяснить сдвиг в мышлении, и добавил ссылку для дальнейшего чтения. Дайте мне знать, если это поможет вам лучше понять ответ на ваш вопрос.

Ответ №2:

передайте ref родительский div в List компоненте.

 ...
componentDidMount() {
    this.props.divElement(this.divRef.current)
  }
  ...
<div ref={this.divRef} className="container1">{listItem}</div>
 

затем в приложении

 divElement = (el) => {
        console.log(el);
        el.childNodes.forEach((element) => element.classList.add('active'))
    }
 

надеюсь, это сработает. вот простой пример
https://codesandbox.io/s/staging-microservice-0574t?file=/src/App.js

Комментарии:

1. Это наивный подход, и он полностью упускает из виду суть реакции.

2. @Webber я согласен с вами, но вопрос был не в подходе к обработке классов в react, а в том, как он может добавить или удалить какой-либо класс.

3. Я понимаю, но добавление «активного класса» — это, по сути, хрестоматийный пример того, в чем преуспевает react. Я бы счел это неудачной возможностью помочь кому-то научиться, предложив взлом, который, скорее всего, вообще не сэкономит время.

Ответ №3:

App.js

 import React, { Component } from "react";
import List from "./List";
import "./styles.css";
export class App extends Component {
  state = { element: [] };
  ref = React.createRef();
  componentDidMount() {
    const {
      current: { divRef = [] }
    } = this.ref;
    divRef.forEach((ele) => ele?.classList?.add("active"));
    console.log(divRef);
    window.addEventListener("keydown", this.keypressed);
  }

  keypressed = (e) => {
    if (e.keyCode == "38" || e.keyCode == "40") this.remove_all_active_list();
  };

  remove_all_active_list = () => {
    const {
      current: { divRef = [] }
    } = this.ref;

    divRef.forEach((ele) => ele?.classList?.remove("active"));
    // boxes.forEach((element) => element.classList.remove('active'));
    console.log(divRef);
  };

  render() {
    return (
      <div className="container0">
        <List divElement={this.divElement} ref={this.ref} />
      </div>
    );
  }
}

export default App;
 

List.js

 import React, { Component } from "react";
import data from "./data";

export class List extends Component {
  // divRef = React.createRef();
  divRef = [];

  render() {
    let listItem = data.map(({ title, src }, i) => {
      return (
        <div
          className="box1"
          key={i}
          id={i}
          ref={(element) => (this.divRef[i] = element)}
        >
          <img src={src} title={title} align="center" alt={title} width={100} />
          <span>{title}</span>
        </div>
      );
    });
    return <div className="container1">{listItem}</div>;
  }
}

export default List;
 

Создайте ссылку для компонента списка и получите доступ к их дочерним элементам. При нажатии клавиши(стрелка вверх/вниз) элементы, имеющие имя класса как «активные», будут удалены. ссылка

Комментарии:

1. да, но я только что добавил решение для его требования. он попросил очистить весь активный класс элемента при нажатии клавиши. ссылка