【问题标题】:inside .map() style "this" Compenent (React.js)内部 .map() 样式“this”组件(React.js)
【发布时间】:2021-08-14 13:46:55
【问题描述】:

我已经映射了一个对象数组,如果我单击其中一个元素,我想将该元素的颜色更改为红色(通过添加一个 CSS 类),但它总是将所有元素着色为红色。我以为 React 会自动获取上下文?我还需要使用“this”吗?

import React, { useState } from "react";

import './Map.css';

const Arr = [
  {
    id: "i1",
    item: "item-1",
  },
  {
    id: "i2",
    item: "item-2",
  },
  {
    id: "i3",
    item: "item-3",
  },
];

const ListElement = (props) => {
  return <li className={props.className} onClick={props.onClick}>{props.children}</li>;
};

const Map = () => {
  const [changedStyle, setChangedSTlye] = useState(false);
  const styleHandler = () => {
    changedStyle ? setChangedSTlye(false) : setChangedSTlye(true);
    console.log("clicked");
    console.log(changedStyle);
  };

  const List = Arr.map((l, index) => (
    <ListElement key={index} onClick={styleHandler} className={changedStyle ? 'map-selected' : ''}>
      {l.item}
    </ListElement>
  ));

  return List;
};

export default Map;
.map-selected{color:red;}

【问题讨论】:

    标签: arrays reactjs dictionary object this


    【解决方案1】:

    而不是有一个标志来改变颜色。您需要维护一个列表,如果选中,它将将所选项目的索引推送到列表中,如果再次单击,则将其弹出。

    const Map = () => {
      const [ selectedItems , setSelectedItems] = useState([]);
    
      const styleHandler = (itemIndex) => {
        if(selectedItems.includes(itemIndex))
        {
          setSelectedItems(prevSelectedItems => prevSelectedItems.filter((item) => item !== itemIndex))
        } else {
          setSelectedItems(prevSelectedItems => [...prevSelectedItems, itemIndex])
        }
      };
    
      const List = Arr.map((l, index) => (
        <ListElement key={index} onClick={() => styleHandler(index)} className={selectedItems.includes(index) ? 'map-selected' : ''}>
          {l.item}
        </ListElement>
      ));
    
      return List;
    };
    

    我们将 index 传递给 styleHandler 。当第一次单击该项目时,我们将项目的索引推送到 state 。如果为第二个项目单击相同的项目,那么我们将其从状态中删除。

    const styleHandler = (itemIndex) => {
        if(selectedItems.includes(itemIndex))
        {
          setSelectedItems(prevSelectedItems => prevSelectedItems.filter((item) => item !== itemIndex))
        } else {
          setSelectedItems(prevSelectedItems => [...prevSelectedItems, itemIndex])
        }
      };
    

    当 selectedItems 中存在项目索引时,我们应用样式

    className={selectedItems.includes(index) ? 'map-selected' : ''}
    

    通过这种方式,无需维护添加标志或修改源数据。

    【讨论】:

    • 非常感谢 Shyam,这非常适合添加 CSS 类,但是当我再次单击该元素时,它会从另一个元素中删除 CSS 类。
    • 更新了答案,过滤器出错了,应该是(item) =&gt; item !== itemIndex)
    • 你是一个绝对的英雄,现在就像一个魅力,而且我理解这个概念!非常感谢
    【解决方案2】:

    问题

    这里的问题是changedStyle 是一个状态变量。因此,它不是数组元素独有的,而是影响所有元素,因为它是react 组件的状态。您需要 changedStyle 作为元素中的属性。

    解决方案

    您的元素中需要有一个changedStyle 标志。您可以在使用onClick 单击时更改数组中的元素。您将根据标志l.changedStyle 动态分配一个类名。您希望您的数组成为一个状态变量,以便 React 组件在更改后重新渲染。

    import React, { useState } from "react";
    
    import './Map.css';
    
    const Arr = [
      {
        id: "i1",
        item: "item-1",
        changedStyle: false
      },
      {
        id: "i2",
        item: "item-2",
        changedStyle: false
      },
      {
        id: "i3",
        item: "item-3",
        changedStyle: false
      },
    ];
    
    const ListElement = (props) => {
      return <li className={props.className} onClick={props.onClick}>{props.children}</li>;
    };
    
    const Map = () => {
      const [arr, setArr] = useState(Arr)
      const styleHandler = (index) => {
        const newArr = [...arr]
        const element = newArr[index]
        newArr.splice(index, 1, {...element, changedStyle: !element.changedStyle}
        setArr(arr)
      };
    
      const List = arr.map((l, index) => (
        <ListElement key={index} onClick={() => styleHandler(index)} className={l.changedStyle ? 'map-selected' : ''}>
          {l.item}
        </ListElement>
      ));
    
      return List;
    };
    
    export default Map;
    

    推荐

    如果您的数组元素中有唯一的idkey,请不要在您的jsx 中使用key={index}。而是使用key={l.id}

    【讨论】:

    • 这涉及到 sourceData 的额外转换,用户现在需要映射其源列表并为其所有项目添加一个新键 changedStyle
    • 没错。有多种方法可以做到这一点,您的答案可能在性能方面更好。
    猜你喜欢
    • 2017-01-27
    • 1970-01-01
    • 2019-04-30
    • 2015-06-25
    • 2019-04-10
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    相关资源
    最近更新 更多