如何仅更改所单击的芯片的颜色,以动态创建的芯片阵列做出反应

时间:2019-12-05 15:25:23

标签: reactjs material-ui

当用户将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访问芯片,因为基本上我被告知不要在我的请求请求中执行此操作。我是新来的反应者,因此在执行此简单任务时遇到问题,我们将不胜感激。

3 个答案:

答案 0 :(得分:0)

看来,解决此问题的最简单方法是在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。

答案 1 :(得分:0)

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

您需要唯一地了解选择了哪个芯片。

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

代码将转换这样的内容(注意:我不完全知道钩子语法,因此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

希望有帮助。还原任何疑问/澄清。

答案 2 :(得分:0)

我解决了这个问题,而不是使用布尔值,而是设置了这样的活动索引值

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);
}