web-dev-qa-db-ja.com

ReactでFont Awesome 5アイコンを切り替える

To Doリスト項目をクリックして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 devツールとインスペクターのスクリーンショットをいくつか撮りました...

以下はReact不完全なコンポーネント(デフォルト) React component while incomplete

そして完了しながら... React component while complete

そして、インスペクターの2つのアイコン要素は、デフォルトで使用されていないものがコメント化されていることに気付きました。 enter image description here

ご覧のとおり、完全な状態とReactツールでのコンポーネントの変更を手動で切り替えることができますが、変更はレンダリングされません。デフォルトの状態を変更して、両方のアイコンが Codepen を作成して別の環境で試してみましたが、この環境は機能しますが、 FA 4.7.0 CDNの使用CodepenおよびFA 4.7.0では、アイコンを調べると、SVGではなくHTML要素にすぎません。

このコンポーネントをFA 5で動作させたいので、どんな助けでも感謝します!

11
user8679481

Font-awesome javascriptはReact rerenderトリガーで再レンダリングしません。新しいfont-awesome svg/javascriptアイコンを使用しないことに問題がなければ、web-fontとしてfont-awesomeを使用できますCSSで。

Index.htmlで、fontawesomeスクリプトを削除し、font-awesome cssスタイルシートを追加します。

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

これでコードが機能するはずです。


他の可能性は、公式の素晴らしいフォントを使用することです(これはもう少し面倒ですが、新しい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

この回答は、ここでの私の回答の編集版です。 ReactでFont Awesome 5を使用するにはどうすればよいですか?

17
brkn

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>
  )
}
11
Adam Stone

別の修正方法は、FA JavaScriptが読み込まれた後、アプリのブートサイクルのどこかでwindow.FontAwesomeConfig = { autoReplaceSvg: 'nest' }を呼び出すことです。

https://stackoverflow.com/a/48552226/5379 および https://fontawesome.com/how-to-use/svg-with-js#auto-replaceも参照してください-svg-nest

2
Ryan McCuaig

今日、ReactJS/Material-UIアプリケーションで同じ問題に直面しました。多くの調査の後、関連する状態が変化したときに要素を強制的にレンダリングするReactのkeyプロパティを使用して、問題を修正しました。

したがって、この例では、renderメソッドを次のように書き換えます。

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.completekeyの一意の値として使用しますが、一意である限り、任意の値を使用できます。

現在、span要素は再レンダリング時に常に削除され、他の要素に置き換えられます。

この答えが将来の探求者に役立つことを願っています。

1
Kumar

上記の議論によると、これはおそらくリアクションバグではなく、フォントの素晴らしいバグです

0
swyx