web-dev-qa-db-fra.com

Icône de bascule de police Awesome 5 avec React

J'essaie de basculer une icône Font Awesome en cliquant sur un élément de la liste des tâches. Voici le composant entier ...

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;

Voici mon FA 5 CDN (directement du site) ...

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

J'ai pris quelques captures d'écran de l'outil de développement et de l'inspecteur de React ...

Voici le composant Réagir alors qu’il est incomplet (valeur par défaut)  React component while incomplete

Et tout en complétant ...  React component while complete

Et les deux éléments d’icône de l’inspecteur, j’ai remarqué que celui qui n’était pas utilisé par défaut est commenté .  enter image description here

Comme vous pouvez le constater, je suis en mesure de basculer manuellement l'état complet et les modifications de composant dans l'outil Réagir, mais la modification n'est pas rendue. J'ai changé l'état par défaut pour m'assurer que les deux icônes sont chargées correctement. J'ai fait un Codepen pour l'essayer dans un environnement différent et celui-ci fonctionne, mais J'utilise le FA 4.7.0 CDN. Avec Codepen et FA 4.7.0, lorsque j'inspecte l'icône, il ne s'agit que d'un élément HTML et non de SVG.

J'aimerais que ce composant fonctionne avec FA 5, toute aide serait la bienvenue!

10
user8679481

Le javascript font-awesome ne rend pas sur un déclencheur de réactif React. Si vous ne souhaitez pas utiliser les nouvelles icônes svg/javascript de font-awesome, vous pouvez utiliser font-awesome en tant que webfont avec css.

Dans votre index.html, supprimez le script fontawesome et ajoutez la feuille de style css font-awesome:

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

Votre code devrait fonctionner maintenant.


L'autre possibilité consiste à utiliser le paquetage officiel font-awesome react (c'est un peu plus compliqué, mais il utilise les nouvelles icônes svg)

Ajoutez les packages nécessaires au projet:

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

Exemple de code:

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} />;
  }
}

Voir le repo de github pour plus d'informations: https://github.com/FortAwesome/react-fontawesome

Cette réponse est une version modifiée de ma réponse ici: Comment puis-je faire en sorte que Font Awesome 5 fonctionne avec React? .

14
brkn

Dans la mesure où FA 5 injecte des éléments svg dans le DOM, il ne fonctionne probablement pas bien avec le DOM virtuel de React. J'espère que c'est quelque chose qu'ils vont corriger, mais une solution de contournement simple consiste simplement à inclure les deux icônes au lieu de les basculer, et à masquer l'une ou l'autre en l'enveloppant dans un conteneur qui applique display: none. Par exemple:

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

Une autre solution consiste à appeler window.FontAwesomeConfig = { autoReplaceSvg: 'nest' } quelque part dans le cycle de démarrage de votre application, après le chargement du code JavaScript FA.

Voir aussi https://stackoverflow.com/a/48552226/53790 et https://fontawesome.com/how-to-use/svg-with-js#auto-replace-svg-nest .

1
Ryan McCuaig

comme discuté ci-dessus c'est probablement un bug de fontawesome, pas un bug de réaction

0
swyx

J'ai rencontré le même problème aujourd'hui avec mon application ReactJS/Material-UI. Après de nombreuses recherches, j'ai résolu le problème en utilisant la propriété key de React qui force le rendu d'un élément lorsque son état associé change.

Donc, dans cet exemple, je voudrais réécrire la méthode de rendu comme ci-dessous:

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>
    );
  }

Ici, j’ai utilisé this.state.complete comme valeur unique pour la key, mais vous pouvez utiliser ce que vous voulez tant qu’ils sont uniques.

Maintenant, l'élément span est toujours supprimé lors du rendu et remplacé par l'autre.

J'espère que cette réponse aide les futurs demandeurs.

0
Kumar