【问题标题】:Toggling Font Awesome 5 icon with React使用 React 切换 Font Awesome 5 图标
【发布时间】:2018-05-22 06:47:48
【问题描述】:

我正在尝试通过单击待办事项列表项来切换 Font Awesome 图标。这是整个组件...

import React from 'react';

import './TodoItem.scss';

class TodoItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      complete: false
    }
    this.toggleComplete = this.toggleComplete.bind(this);
  }

  toggleComplete() {
    this.setState(prevState => ({
      complete: !prevState.complete
    }));
  }

  render() {
    const incompleteIcon = <span className="far fa-circle todo-item-icon"></span>;
    const completeIcon = <span className="far fa-check-circle todo-item-icon"></span>;

    return (
      <div className="todo-item" onClick={this.toggleComplete}>
        {this.state.complete ? completeIcon : incompleteIcon}
        <span className="todo-item-text">{this.props.item}</span>
      </div>
    );
  }
}

export default TodoItem;

这是我的 FA 5 CDN(直接来自网站)...

<script defer src="https://use.fontawesome.com/releases/v5.0.1/js/all.js"></script>

我截取了一些 React 开发工具和检查器的屏幕截图...

这是不完整的 React 组件(默认)

虽然完成...

检查器中的两个图标元素,我注意到默认情况下未使用的元素被注释掉了。

如您所见,我可以在 React 工具中手动切换完整状态和组件更改,但不会呈现更改。我更改了默认状态以确保两个图标都正确加载并且它们是正确的。我创建了一个Codepen 以在不同的环境中尝试它,这个有效,但我使用的是 FA 4.7.0 CDN。使用 Codepen 和 FA 4.7.0,当我检查图标时,它只是一个 HTML 元素而不是 SVG。

我想让这个组件与 FA 5 一起工作,所以任何帮助都将不胜感激!

【问题讨论】:

  • 嗨,我把你的代码放到了一个codepen中,它似乎可以工作。 codepen.io/swyx/pen/mqZxoL 所以很可能你有某种 FA 加载问题。
  • @swyx 自己尝试过,这似乎是一个 FA 问题,代码在任何其他情况下都有效。 React 是否有可能不会渲染它,因为元素之间的唯一区别是类而不是内容?感谢您的帮助,不知道这是什么。
  • 不,您可以通过在该类上放置任何其他具有某种样式的类来检查是否是这种情况
  • @swyx 是的,我没有想到这一点。哎呀。

标签: javascript reactjs font-awesome font-awesome-5


【解决方案1】:

字体很棒的 javascript 不会在 React 重新渲染触发器上重新渲染。如果您可以不使用新的 font-awesome svg/javascript 图标,您可以使用 font-awesome 作为带有 css 的 webfont。

在您的 index.html 中,删除 fontawesome 脚本,并添加 font-awesome css 样式表:

<link href="https://use.fontawesome.com/releases/v5.0.2/css/all.css" rel="stylesheet">

您的代码现在应该可以工作了。


另一种可能是使用官方的 font-awesome react 包(有点麻烦,但它使用了新的 svg 图标)

为项目添加必要的包:

yarn add @fortawesome/fontawesome @fortawesome/react-fontawesome
yarn add @fortawesome/fontawesome-free-regular @fortawesome/fontawesome-free-solid

示例代码:

import fontawesome from '@fortawesome/fontawesome'
import FontAwesomeIcon from '@fortawesome/react-fontawesome'
import { faCircle as fasCircle } from '@fortawesome/fontawesome-free-solid'
import { faCircle as farCircle } from '@fortawesome/fontawesome-free-regular'

const Circle = ({ filled, onClick }) => {

  return (
    <div onClick={onClick} >
      <FontAwesomeIcon icon={filled ? farCircle : fasCircle}/>
    </div>
  );
};

class App extends React.Component {
  state = { filled: false };

  handleClick = () => {
    this.setState({ filled: !this.state.filled });
  };

  render() {
    return <Circle filled={this.state.filled} onClick={this.handleClick} />;
  }
}

更多信息请参见 github 仓库:https://github.com/FortAwesome/react-fontawesome

这个答案是我的答案的编辑版本:How can I get Font Awesome 5 to work with React?

【讨论】:

【解决方案2】:

由于 FA 5 将 svg 元素注入到 DOM 中,它可能无法很好地与 React 的虚拟 DOM 配合使用。希望这是他们会解决的问题,但一个简单的解决方法是只包含两个图标而不是切换它们,并通过将其包装在应用 display: none 的容器中来隐藏其中一个或另一个。例如:

renderChatButton() {
  const unread = this.state.unread
  const normalIcon = <i className='far fa-comment' />
  const unreadIcon = <i className='fas fa-comment' />
  return (
    <div className='header-button' onClick={ this.toggleChat }>
      <span className={ unread ? 'hidden' : '' }>{ normalIcon }</span>
      <span className={ unread ? '' : 'hidden' }>{ unreadIcon }</span>
    </div>
  )
}

【讨论】:

    【解决方案3】:

    看起来另一个解决方法是在加载 FA JavaScript 后,在应用启动周期的某个位置调用 window.FontAwesomeConfig = { autoReplaceSvg: 'nest' }

    另请参阅https://stackoverflow.com/a/48552226/53790https://fontawesome.com/how-to-use/svg-with-js#auto-replace-svg-nest

    【讨论】:

      【解决方案4】:

      我今天在使用 ReactJS/Material-UI 应用程序时遇到了同样的问题。经过大量研究后,我通过使用 React 的 key 属性解决了这个问题,该属性强制元素在其关联状态更改时呈现。

      所以,在这个例子中,我将重写渲染方法如下:

      render() {
          const icon = this.state.complete ? (<span key={this.state.complete} className="far fa-circle todo-item-icon"/>) : (<span key={this.state.complete} className="far fa-check-circle todo-item-icon"/>);
      
          return (
            <div className="todo-item" onClick={this.toggleComplete}>
              {icon}
              <span className="todo-item-text">{this.props.item}</span>
            </div>
          );
        }
      

      在这里,我使用 this.state.complete 作为 key 的唯一值,但你可以使用任何你喜欢的值,只要它们是唯一的。

      现在,span 元素在重新渲染时总是被移除并被另一个元素替换。

      希望这个答案对未来的求职者有所帮助。

      【讨论】:

        【解决方案5】:

        根据上面的讨论,这可能是一个很棒的错误,而不是反应错误

        【讨论】:

        • 不是错误。带有 JS 的 SVG 只是与虚拟 DOM 引擎不兼容。
        【解决方案6】:

        你可以使用 to function 而不是 class 但在此之前你需要为 reactjs 代码下载 react fontawesome 包:

            import React from  'react';
            import Menuitems from '././Menuitems';
            import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
            import { faTimes, faBars } from '@fortawesome/free-solid-svg-icons';
            
            const Menu =() => {
            
               const [item, setItem]= React.useState(false);
            
               const handleitem =()=>{
                 setItem(!true);
               }
                return(
                    <>
                      <Container>
                          <nav>
                               <h1> react </h1>
                         
                             <div className="menu-icon" onClick={handleitem}>
                                <FontAwesomeIcon icon={item ? faTimes :  faBars } size="3x"/>
                             </div>
                          </nav>
                       </Container>
                    </>
                );
            }
            
            export default Menu;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-03-12
          • 2019-06-12
          • 2021-12-22
          • 2020-09-20
          • 2015-07-14
          • 2021-05-04
          • 2019-01-24
          • 1970-01-01
          相关资源
          最近更新 更多