【问题标题】:how to change only the color of the chip clicked in react from a dynamically created array of chips如何仅更改从动态创建的芯片阵列中单击的芯片的颜色
【发布时间】:2019-12-05 15:25:23
【问题描述】:

当用户将 excel 或 csv 文件拖放到我身上时,我会从该文件的列中动态创建 material-ui 芯片。我向他们展示了列并允许用户单击他们想要的列,然后我根据与该列关联的数据为他们构建列表。一切正常,除了当用户单击芯片时,我希望芯片变为绿色并添加一个复选标记以表明该芯片已被选中。他们可以选择许多筹码,因此如果他们选择另一个筹码,我希望该筹码变为绿色。他们还可以点击 x 并取消选择芯片,此时我希望芯片返回原始颜色并检查以消失。

  return (
  <div>
    {
      props.dropdownkeys.map((value, index) => (
        <Chip label={value}
          icon={<CheckIcon key={index} id={`check_${value}`} color='primary' visibility={clickedChip ? 'visible' : 'hidden'}/>}
          key={index}
          onClick={() => addChip(value, index)}
          onDelete={() => deselectChip(value, index)}
          size='small'
          id={`chip_${value}`}
          ref={setChipRef}
          className={clickedChip ? classes.chipSelected : classes.chip }
        />
      ))
    }
  </div>
);

这是我动态创建的芯片,我试图基于 useState 挂钩来触发以更改 clickedchip

 const [clickedChip, setClickedChip] = useState(false);

这是我的 addchip 功能

function addChip(value: number | string, index: number) {
  debugger;
  const chipClicked = getClickedChip(index);

  if (chipClicked !== null) {
    // chipClicked[0].style.backgroundColor = 'green';
    // (chipClicked[0].firstChild as HTMLElement).style.color = 'red';
    // (chipClicked[0].firstChild as HTMLElement).attributes[6].value = 'visible';
  }

  const getCols = props.excelDocumentObj.filter((column) => {
    if (column[value] !== undefined) {return column[value];} else { return null;}
  }); 
  if (props.storeString !== '') {
    props.setStoreString(',');
  }

  const rowLen = getCols.length;
  for (const [i, storeNum] of getCols.entries()) {
    if(typeof storeNum[value] === 'number') {
      if(rowLen !== i + 1) {
        props.setStoreString(`${storeNum[value] },`);
      }
      else {
        props.setStoreString(`${storeNum[value]}`);
      }
    }
  }
  creatorStore.handleStoreListFromExcel(props.storeString);
}

我遇到的问题是我正在更改渲染器中的所有芯片,而不是我想要的选定芯片。我不想通过 dom 访问芯片,因为基本上我被告知不要在我的拉取请求中这样做。我是新手,所以我在执行这个简单的任务时遇到了问题,我们将不胜感激。

【问题讨论】:

    标签: reactjs material-ui


    【解决方案1】:

    我修复了这个问题,而不是使用布尔值我设置了一个像这样的活动索引值

    const [activeIndex, setActiveIndex] = useState(-1);
    

    然后在我的渲染中我把它改成了这个

    return (
      <div>
        {
          props.dropdownkeys.map((value, index) => (
            <Chip label={value}
              icon={<CheckIcon key={index} id={`check_${value}`} color='primary' visibility={index === activeIndex ? 'visible' : 'hidden'}/>}
              key={index}
              onClick={() => addChip(value, index)}
              onDelete={() => deselectChip(value, index)}
              size='small'
              id={`chip_${value}`}
              ref={setChipRef}
              className={index === activeIndex ? classes.chipSelected : classes.chip }
            />
          ))
        }
      </div>
    );
    

    然后在我的 addclick 中我调用了更新函数

    function addChip(value: number | string, index: number) {
      debugger;
     setClickedChip(index, true);
    
      const getCols = props.excelDocumentObj.filter((column) => {
        if (column[value] !== undefined) {return column[value];} else { return null;}
      }); 
      if (props.storeString !== '') {
        props.setStoreString(',');
      }
    
      const rowLen = getCols.length;
      for (const [i, storeNum] of getCols.entries()) {
        if(typeof storeNum[value] === 'number') {
          if(rowLen !== i + 1) {
            props.setStoreString(`${storeNum[value] },`);
          }
          else {
            props.setStoreString(`${storeNum[value]}`);
          }
        }
      }
      creatorStore.handleStoreListFromExcel(props.storeString);
    }
    

    依次调用这个函数

     function setClickedChip(index: number, value: boolean) {
      if (value) {
        setActiveIndex(index);
      }
      else {
        setActiveIndex(-1);
      }
    }
    

    那么我最喜欢的就是这个

    function deselectChip(value: number | string, index: number) {
      setClickedChip(index, false);
      let deleteString = props.storeString;
      const getCols = props.excelDocumentObj.filter((column) => {
        if (column[value] !== undefined) {return column[value];} else {return null;}
      });
      for(const column of getCols) {
        deleteString = removeValue(deleteString, column[value], ',');
      }
      props.deleteFromStoreString(deleteString);
      creatorStore.handleStoreListFromExcel(props.storeString);
    }
    

    【讨论】:

      【解决方案2】:

      看来解决这个问题的最简单方法是在 props.dropdownkeys 中添加一个名为“selected”的属性。这将是一个布尔值。请注意,您可能必须在父组件中定义“props.dropdownkeys”的任何地方添加它。

      那么您的代码将如下所示:

          return (
        <div>
          {
            props.dropdownkeys.map((value, index) => (
              <Chip label={value}
                icon={<CheckIcon key={index} id={`check_${value}`} color='primary' visibility={value.selected ? 'visible' : 'hidden'}/>}
                key={index}
                onClick={() => addChip(value, index)}
                onDelete={() => deselectChip(value, index)}
                size='small'
                id={`chip_${value}`}
                ref={setChipRef}
                className={value.selected ? classes.chipSelected : classes.chip }
              />
            ))
          }
        </div>
      );
      

      请注意,使用这种方法,您需要添加一个函数来切换您初始化 props.dropdownkeys 的父组件中的选定属性。假设您调用它 toggleChip(),然后您可以使用 onClick 事件处理程序调用它。像

      onClick={() => props.toggleChip(value, index)}
      

      您还可以将 clickedChip 状态变量更改为一个数组,该数组映射到具有 true 或 false 值的每个芯片。

      【讨论】:

        【解决方案3】:

        这里有一个逻辑错误。您正在为所有筹码使用一个布尔变量 (clickedChip)。因此,如果选择了任何一个芯片,则 clickedChip 变为真,className={clickedChip ? classes.chipSelected : classes.chip} 对所有筹码都变为真。

        您需要唯一知道选择了哪个芯片。

        所以,你需要做的是:
        - 最初,将 clickedChip 初始化为 null
        - 在您的 clickedChip 变量中,仅存储与特定芯片相关的唯一值(例如某些 id 或键)
        - 在您的类名或图标条件中,将该特定芯片的唯一值与保存的值匹配,并应用逻辑显示绿色或使图标可见
        - 单击交叉或取消选择时,将 clickedChip 设置为 null

        代码将转换成这样(注意:我并不完全了解 hooks 语法,所以 setState 已经解释过):

        state = { clickedChip: null }
        
        setClickedChip = (uniqueChipId) => {
            this.setState({ clickedChip: uniqueChipId }) 
        }
        
        render() {
        ...
          return (
            <div>
              {
                props.dropdownkeys.map((value, index) => (
                  <Chip label={value}
                    icon={<CheckIcon key={index} id={`check_${value}`} color='primary' visibility={clickedChip === `chip_${value}` ? 'visible' : 'hidden'}/>}
                    key={index}
                    onClick={() => addChip(value, index)}
                    onDelete={() => deselectChip(value, index)}
                    size='small'
                    id={`chip_${value}`}
                    ref={setChipRef}
                    className={clickedChip === `chip_${value}` ? classes.chipSelected : classes.chip }
                  />
                ))
              }
            </div>
          );
        ...
        

        chip_${value} 和 uniqueChipId 是唯一的芯片 ID

        希望对您有所帮助。如有任何疑问/澄清,请回复。

        【讨论】:

        • 感谢您的回复,这有点像我对上面的索引所做的,但现在发生了什么我点击一个,它改变了,但是当我点击另一个时,他们点击的第一个改变回到蓝色,另一个变成绿色。我希望他们两个都是绿色的,直到他们用 x 按钮取消选择芯片
        • 在这种情况下,您需要处理@chickenjake 所写的内容。在下拉键的每个对象内,添加一个选定的变量并将其切换为 true 或 false。另一种方法可以是仅在您的解决方案中,您可以将所有选定的 id 存储在一个数组中(而不是 activeIndex 或 clickedChip),然后检查数组中是否存在相应的 id 并将其设为绿色。当用户再次点击时,从数组中删除 id。
        猜你喜欢
        • 2016-09-18
        • 2023-03-13
        • 2020-07-04
        • 1970-01-01
        • 2020-09-02
        • 1970-01-01
        • 1970-01-01
        • 2019-12-22
        • 1970-01-01
        相关资源
        最近更新 更多