简体   繁体   English

带有 React 钩子的动态类名没有按预期工作

[英]Dynamic className with React hooks not working as expected

This is the code for a custom MultiSelect component I'm writing.这是我正在编写的自定义 MultiSelect 组件的代码。 I want each button to have class="selected" when that value is selected.我希望每个按钮在选择该值时都有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>
  )
}

The class name never displays as selected , and doesn't change when option.selected changes. class 名称永远不会显示为selected ,并且不会在option.selected更改时更改。 When I add {option.selected? 'selected': ''}当我添加{option.selected? 'selected': ''} {option.selected? 'selected': ''} under {option.name} inside the button as raw text, it displays and changes as expected. {option.selected? 'selected': ''}在按钮内的{option.name}下作为原始文本,它按预期显示和更改。

When I change it to either of the following, it works:当我将其更改为以下任一时,它可以工作:

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

Can anybody explain why plain old className={option.selected? 'selected': ''}谁能解释为什么普通的旧className={option.selected? 'selected': ''} className={option.selected? 'selected': ''} isn't working? className={option.selected? 'selected': ''}不起作用?

I'm going to analyze your solution.我将分析您的解决方案。

  1. className={option.selected? 'selected': ''} className={option.selected? 'selected': ''} could be rewrite to className={option.selected && 'selected' } if the property is defined the operation result will be 'selected' for operator precedence, javascript always evaluate from left to right. className={option.selected? 'selected': ''}可以重写为className={option.selected && 'selected' }如果定义了属性,则操作结果将为运算符优先级'selected',javascript 总是从左到右计算。
  2. MultiSelect is a stateless component so your options props come from the hight order component, one way is an onClick event send as a parameter the id of the option, and in the parent change the value of the option. 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" />;
};

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

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