e.target.classList.{添加||删除 ||切换 } dangerouslySetInnerHtml?

Does e.target.classList.{add || remove || toggle } dangerouslySetInnerHtml?

想问问对 React 有更多经验的人,因为我似乎找不到明确的答案。我知道你不想直接向 DOM 添加文本,这就是为什么 React 让你写 dangerouslySetInnerHtml 来设置它。

但是 classList.{ add || remove || toggle } 呢?使用 classList.add() || .remove() 是否等同于 dangerouslySetInnerHtml?我也应该担心这样做吗?

例子 - 从组件内部呈现列表的函数 bootstrap css.

问题:在鼠标悬停时将 add/remove .active 设置为 li className

import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';

const RenderList = (array, position = 'text-center') => {
    const handleMouseEnter = e => {
        e.target.classList.add('active');
    };

    const handleMouseLeave = e => {
        e.target.classList.remove('active');
    };

    return (
        <ul className={`list-group ${position}`}>
            {array.map(({ href, key, label, rel, target }) => (
        <a key={key} href={href} rel={rel} target={target} fontSize={1.2}>
          <li
            className={`list-group-item '${key}'`}
          
            data-id={key}
            onMouseEnter={handleMouseEnter}
            onMouseLeave={handleMouseLeave}
          >
            {label}
          </li>
        </a>
            ))}
        </ul>
    );
};
export default RenderList;

问题是 - 我试过将其设置为状态,但它会同时影响所有 li(我在其他问题中看到过这个问题 - 尽管不是针对功能组件,而是针对类)

这里安全吗?我在浏览器中没有看到任何警告。

如果不安全,有什么替代方案?我尝试使用 li 键中的 data-id 属性,但我无法完全理解单个元素的 useState...

编辑:有人提出了一个问题作为可能的答案,但它建议为每个列表项创建一个单独的状态实例,这似乎不是一个很好的解决方案。

我想我可能已经找到了解决方法,但我不确定这是否是正确的方法。它仍然操纵 DOM,但使用状态 - 所以 React 可以决定何时执行它:

import React, { useState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';

const RenderList = (array, position = 'text-center') => {
const [isActive, setIsActive] = useState(null);
const [isNotActive, setIsNotActive] = useState(null);

const handleMouseEnter = e => {
  setIsActive(e.target.classList.add('active'));
};

const handleMouseLeave = e => {
  setIsNotActive(e.target.classList.remove('active'));
};

    return (
        <ul className={`list-group ${position}`}>
            {array.map(({ href, key, label, rel, target }) => (
        <a key={key} href={href} rel={rel} target={target} fontSize={1.2}>
          <li
            className={`list-group-item '${key}'`}
          
            data-id={key}
            onMouseEnter={handleMouseEnter}
            onMouseLeave={handleMouseLeave}
          >
            {label}
          </li>
        </a>
            ))}
        </ul>
    );
};
export default RenderList;

希望得到反馈

手动修改 DOM 是 React 中的反模式

React 是一个数据优先的 UI 库,这意味着数据决定了它应该如何呈现,并且它(几乎)永远不需要读取 DOM。它只写入 DOM,并使用其内部差异算法计算要在 DOM.

中更新的最小块

当我们自己改变 DOM 时,React 不会意识到我们的变化,并且可能会在下一个渲染阶段消除我们的努力。

鼠标悬停时切换样式

尽可能使用 CSS 选择器而不是 JavaScript 选择器来设置组件样式。在这种情况下,它将是一个简单的选择器:

.list-group li:hover {
  /* `.active` styles here */
}

如何在每个项目上切换 类?

为了避免管理列表组件中每个单独项目的状态,我会制作一个 Item 组件来管理它自己的状态和事件,让父列表专注于它的实际逻辑。

const { useState } = React;

// Manages its own state and events, making it 
// possible to toggle the class here instead.
const Item = ({ to }) => {
  const [active, setActive] = useState(false);
  
  return (
    <li
      className={active? 'active' : ''} 
      onMouseEnter={() => setActive(true)}
      onMouseLeave={() => setActive(false)}
    >
      <a data-link={to}>{to}</a>
    </li>
  );
};

// No more class toggling logic needed here.
const List = ({ items }) => (
  <ul>
    {items.map((itemProps) => <Item {...itemProps} />)}
  </ul>
);

ReactDOM.render(
  <List items={[{ to: '/home' }, { to: '/foo' }]} />,
  document.querySelector('[data-role-react-root]')
);
.active {
  background: red;
}
<div data-role-react-root></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>