带有React钩子的动态className无法正常工作

问题描述 投票:0回答:1

这是我正在编写的自定义MultiSelect组件的代码。选择该值时,我希望每个按钮都具有class="selected"

import React from 'react'

import './styles.scss'

export default function MultiSelect({
  name = '',
  options = [],
  onChange = () => {},
}) {
  const clickOption = e => {
    e.preventDefault()
    onChange(
      options.map(o => {
        if (o.value === e.target.value) o.selected = !o.selected
        return o
      }),
    )
  }

  return (
    <div className="multiselect" name={name}>
      {options.map(option => (
        <button
          key={option.value}
          value={option.value}
          onClick={e => clickOption(e)}

          {/* here */}
          className={option.selected ? 'selected' : ''}
        >
          {option.name}
        </button>
      ))}
    </div>
  )
}

类名从不显示为selected,并且当option.selected更改时也不会更改。当我在按钮内的{option.selected ? 'selected' : ''}下将{option.name}作为原始文本添加时,它会显示并按预期进行更改。

当我将其更改为以下任意一项时,它将起作用:

<button className={`${option.selected ? 'selected' : ''}`}>
<!-- OR -->
<button className={'' + (option.selected ? 'selected' : '')}>

有人可以解释为什么旧的className={option.selected ? 'selected' : ''}无法正常工作吗?

javascript reactjs
1个回答
0
投票

我将分析您的解决方案。

  1. [className={option.selected ? 'selected' : ''}可以重写为className={option.selected && 'selected' },如果定义了该属性,将为运算符优先级选择操作结果,javascript始终从左到右求值。
  2. [MultiSelect是一个无状态组件,因此您的选项道具来自高阶组件,一种方法是onClick事件将选项的ID作为参数发送,并在父级中更改选项的值。
import React, { useState } from 'react';
import './styles.scss';

const MultiSelect = ({
    name = '',
    options = [],
    onChange = () => {},
}) => {
    const handleClick = (id) => () => onChange(id);
    return (
        <div className="multiselect" name={name}>
            {options.map((option) => (
                <button
                    key={option.value}
                    value={option.value}
                    onClick={handleClick(option.id)}
                    className={option.selected && 'selected'}
                >
                    {option.name}
                </button>
            ))}
        </div>
    );
};

const Parent = ({ }) => {
    const [options, setOptions] = useState([{
        id: 1,
        value: 1,
        selected: true,
        name: 'Hello',
    },
    {
        id: 2,
        value: 2,
        selected: false,
        name: 'World',
    },
    ]);

    const handleChange = (id) => {
        const option = options.find((option) => option.id === id);
        setOptions(
            ...options.filter((option) => option.id !== id),
            {
                ...option,
                selected: !option.selected,
            },
        );
    };

    return <MultiSelect options={options} onChange={handleChange} name="Example" />;
};
© www.soinside.com 2019 - 2024. All rights reserved.