简体   繁体   English

如何在 React JS 中使用 forEach

[英]How to use forEach in react js

I want to create a function which iterate over all element with same class and remove a specific class.我想创建一个 function,它遍历具有相同 class 的所有元素并删除特定的 class。

It could be done easily using JavaScript.使用 JavaScript 可以轻松完成。

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

But how can I do this similar thing is ReactJs. The problem which I am facing is that I can't use document.querySelectorAll(".box1") in React but, I can use React.createRef() but it is not giving me all elements, it's only giving me the last element.但是我怎么能做这个类似的事情是 ReactJs。我面临的问题是我不能在 React 中使用document.querySelectorAll(".box1")但是,我可以使用React.createRef()但它没有给出我所有的元素,它只给我最后一个元素。

This is my React Code这是我的反应代码

App.js应用程序.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清单.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;

Please tell me how can I over come this problem.请告诉我如何解决这个问题。

The short answer简短的回答

You wouldn't.你不会。

Instead you would conditionally add and remove the class to the element, the component, or to the collection.map() inside your React component.相反,您可以有条件地向元素、组件或 React 组件内的collection.map()添加和删除 class。

Example例子

Here's an example that illustrates both:这是一个说明两者的示例:

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;

So in your case:所以在你的情况下:

  • You could pass active prop to the <ListItem /> component and use props.active as the condition.您可以将active prop 传递给<ListItem />组件并使用props.active作为条件。

  • Alternatively you could send activeIndex to <List /> component and use index === activeIndex as the condition in your map.或者,您可以将activeIndex发送到<List />组件并使用index === activeIndex作为 map 中的条件。

Explanation解释

Instead of adding or removing classes to a HTMLElement react takes care of rendering and updating the whole element and all its properties (including class - which in react you would write as className ). React 不会向 HTMLElement 添加或删除类,而是负责呈现和更新整个元素及其所有属性(包括class - 在 React 中,您将编写为className )。

Without going into shadow dom and why react may be preferable, I'll just try to explain the shift in mindset:在不讨论 shadow dom 以及为什么 react 可能更可取的情况下,我将尝试解释思维方式的转变:

Components do not only describe html elements, but may also contain logic and behaviour.组件不仅描述了 html 个元素,还可能包含逻辑和行为。 Every time any property changes, at the very least the render method is called again, and the element is replaced by the new element (ie before without any class but now with a class).每次任何属性更改时,至少再次调用 render 方法,并且元素被新元素替换(即之前没有任何 class 但现在有一个类)。

Now it is much easier to change classes around.现在改变类更容易了。 All you need to do is change a property or modify the result of a condition (if statement).您需要做的就是更改属性或修改条件(if 语句)的结果。

So instead of selecting some elements in the dom and applying some logic them, you would not select any element at all;因此,不是选择 dom 中的某些元素并对其应用一些逻辑,而是根本不会 select 任何元素; the logic is written right inside the react component, close to the part that does the actual rendering.逻辑就写在 React 组件内部,靠近执行实际渲染的部分。

Further reading延伸阅读

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

Please don't hessitate to add a comment if something should be rephrased or added.如果应该改写或添加某些内容,请不要犹豫添加评论。

pass the ref to the parent div in List component.ref传递给List组件中的父 div。

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

then in App然后在应用程序

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

hope this will work.希望这会奏效。 here is a simple example https://codesandbox.io/s/staging-microservice-0574t?file=/src/App.js这是一个简单的例子https://codesandbox.io/s/staging-microservice-0574t?file=/src/App.js

App.js应用程序.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清单.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;

Create ref for List component and access their child elements.为 List 组件创建 ref 并访问它们的子元素。 When key pressed(up/down arrow) the elements which has classname as 'active' will get removed.当按下键(向上/向下箭头)时,类名为“活动”的元素将被删除。 reference参考

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM