2
votes

Comment ajouter de la couleur à une partie spécifique d'une chaîne dans React en utilisant replace?

Je voudrais rendre tous les nombres dans une chaîne rouge et ensuite le rendre avec React. Voici ce que j'essaie de faire (j'ai créé une application en utilisant create-react-app et remplacé le contenu d'App.js par le mien):

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    const str = 'foo123bar';

    const strColor = 
      str.replace(/\d+/, match => <span style={{color: 'red'}}> {match} </span> );

    return (
      <div className="App">
        {strColor}
      </div>
    );
  }
}

export default App;

En conséquence, seule la ligne foo [object Object] bar a été rendue dans la fenêtre.

Alors, comment ajouter un style en ligne à JSX?

p>


1 commentaires

Je pense que la question à laquelle vous essayez vraiment de répondre est de savoir comment remplacer des parties d'une chaîne par un composant (dans ce cas, une balise avec un style. Ce problème est documenté dans la réaction github, notez qu'il existe de nombreuses options sans que vous ayez à définir dangereusement votre code HTML interne: github. com / facebook / react / issues / 3386


3 Réponses :


3
votes

J'ai pu résoudre ce problème en utilisant «dangerouslySetInnerHTML».

class App extends React.Component {
  render() {
      let str = 'foo123bar';

      const strColor = str.replace(/\d+/, match => `<span style="color: red">${match} </span>` );

    return (
        <div className="App"
         dangerouslySetInnerHTML={{__html: 
          strColor}}>
      </div>
);

} }


1 commentaires

La question d'OP porte principalement sur l'ajout de style en ligne - je pense qu'il vaut la peine de noter votre modification de la définition de style en ligne dans votre réponse. Notez également qu'il existe de nombreuses options sans qu'il soit nécessaire de définir dangereusement le code HTML interne: github.com/facebook/react / issues / 3386



2
votes

Vous ne pouvez pas insérer du HTML dans une chaîne pour qu'il soit rendu dans React, cela existe en tant que protection contre XSS.

Ce que vous pouvez faire dans un cas comme celui-ci est quelque chose comme:

const str = 'foo123bar456baz897ban';
let strCopy = str;
const list = [];

while(strCopy) {
    const text = strCopy.split(/\d+/, 1)[0];
    list.push(text);
    const match = strCopy.match(/\d+/);
    if (!match) {
        break;
    }
    list.push(match[0]);
    strCopy = strCopy.substring(match.index + match[0].length);
}

return (
  <div className="App">
    {list.map((elem, index) => index % 2 === 0
         ? elem
         : <span style="color: red">{elem}</span>
    )}
  </div>
);

Pour un exemple plus complexe, vous aurez besoin d'une logique plus complexe. Par exemple. plusieurs parties peuvent être stylisées - vous pouvez trouver toutes les correspondances et les parties non correspondantes et les mettre dans une liste dans le bon ordre avec un indicateur si vous utilisez la plage ou non. Quelque chose comme:

list.map((elem) => elem.isColored ? <span style="color: red">{elem.value}</span> : elem.value)

MODIFIER

Comme mentionné dans les commentaires, voici une implémentation pour plusieurs éléments:

const str = 'foo123bar';

const coloredStr = str.match(/\d+/);
const [before, after] = str.split(/\d+/)

return (
  <div className="App">
    {before}
    {coloredStr && coloredStr[0] && 
       <span style="color: red">{coloredStr[0]}</span>
    }
    {after}
  </div>
);


5 commentaires

J'ai pensé au fractionnement, mais que faire si j'ai str = 'foo123bar456baz897ban' ?


Comme je l'ai mentionné, ce sera un peu délicat, je vais essayer de coder l'exemple en premier et modifierai ma réponse en conséquence :)


C'est ici. Je n'ai pas testé la partie rendu, juste la boucle, mais ça devrait aller. N'hésitez pas à commenter si j'ai manqué quelque chose. :)


Merci! Si je ne me trompe pas, j'ai utilisé une approche similaire à partir d'un fil de discussion sur github. github.com/facebook/react/issues/3386#issuecomment-404464020


Oui, l'idée est la même, mais le code de ce commentaire est beaucoup plus agréable. : +1: Je voulais garder le mien aussi simple que possible (sans utiliser le drapeau regex g et tout) :)



2
votes

"Alors, comment ajouter un style en ligne à JSX?"

Pour répondre à la question que vous avez posée, votre ligne:

const strColor = str.replace(/\d+/, match => <span style={{color: 'red'}}> {match} </span> );

renvoie une chaîne - donc le instruction d'objet style = {{color: 'red'}}> ne sera pas échappé.

Ajoutez plutôt le style en ligne avec une définition de chaîne, référencez les guillemets doubles et les accolades supprimées:
{match}

Vous pouvez ajouter d'autres styles en séparant les paires clé: valeur par des virgules:
{match}


Notez que cela ne fonctionnera pas
La question à laquelle vous essayez vraiment de répondre est de savoir comment remplacer des parties d'une chaîne par un composant (dans ce cas, une balise avec un style. Ce problème est documenté dans les problèmes de react github page, notez qu'il existe de nombreuses options sans vous obliger à définir dangereusement votre code HTML interne comme indiqué dans plusieurs réponses précédentes: https://github.com/facebook/react/issues/3386


6 commentaires

Merci! Alors, quelle est la façon la plus simple de faire cela?


@EugeneBarsky Il y a un dépôt Github mentionné dans le fil de discussion que vous pouvez intégrer à votre projet via Git. Voici le lien vers le dépôt: github.com/iansinnott/react-string-replace. Ce dépôt fournit une fonction appelée reactStringReplace () qui gérera votre cas d'utilisation. Si vous faites défiler la documentation README, vous trouverez un exemple appelé «Exemple plus réaliste» qui répond directement à vos besoins. J'espère que cela t'aides!


Je vous remercie! Enfin, j'ai modifié l'une des solutions de la page de discussion, et cela semble parfaitement fonctionner pour mon projet.


heureux de l'entendre!


C'était celui-ci: github.com/facebook/react/issues/3386#issuecomment -404464020 ‌. Le principal avantage est que non seulement cela fonctionne, mais je comprends comment. :)


Aussi probablement plus rapide / plus facile / plus lisible que l'importation d'une bibliothèque externe. Bonne idée!