web-dev-qa-db-fra.com

Réagissez les sauts de ligne d'affichage à partir de la zone de texte enregistrée

Utilisation de Facebook React. Dans une page de paramètres, j’ai une textarea multiligne où un utilisateur peut entrer du texte multiligne (dans mon cas, une adresse). 

<textarea value={address} />

Lorsque j'essaie d'afficher l'adresse, quelque chose comme {address} ne montre pas les sauts de ligne et se trouve sur une seule ligne. 

<p>{address}</p>

Des idées pour résoudre ça? 

49
denislexic

Il n'y a aucune raison d'utiliser JS. Vous pouvez facilement dire au navigateur comment gérer une nouvelle ligne à l'aide de la propriété CSS white-space:

white-space: pre-line;

pré-ligne 

Les séquences d'espaces sont réduites. Les lignes sont brisées à caractères de nouvelle ligne, à <br>, et au besoin pour remplir les zones de ligne.

Découvrez cette démo:

<style>
  #p_wrap {
    white-space: pre-line;
  }
</style>

<textarea id="textarea"></textarea>
<p id="p_standard"></p>
<hr>
<p id="p_wrap"></p>
<script>
  textarea.addEventListener('keypress', function(e) {
    p_standard.textContent = e.target.value
    p_wrap.textContent = e.target.value
  })
</script>

 browser support for pre-line

147
enapupe

Ceci est à prévoir, vous devrez convertir les caractères de la nouvelle ligne (\ n) en sauts de ligne HTML. 

Un article sur son utilisation dans react: https://medium.com/@kevinsimper/react-newline-to-break-nl2br-a1c240ba746#.l9sbqp5aw

Pour citer un article:

Parce que vous savez que tout dans React est une fonction, vous ne pouvez pas vraiment le faire

this.state.text.replace(/(?:\r\n|\r|\n)/g, '<br />')

Comme cela renverrait une chaîne avec des noeuds DOM à l'intérieur, cela n'est pas autorisé non plus, car il doit s'agir uniquement d'une chaîne.

Vous pouvez alors essayer de faire quelque chose comme ceci:

{this.props.section.text.split(“\n”).map(function(item) {
  return (
    {item}
    <br/>
  )
})}    

Cela n’est pas autorisé non plus, car React est une fonction pure et deux fonctions peuvent être côte à côte.

tldr. Solution

{this.props.section.text.split(“\n”).map(function(item) {
  return (
    <span>
      {item}
      <br/>
    </span>
  )
})}

Maintenant, nous encapsulons chaque saut de ligne dans une étendue, et cela fonctionne bien car l’affichage de cette dernière est en ligne. Maintenant, nous avons une solution de rupture de ligne nl2br qui fonctionne

28
Mark Milford

La solution consiste à définir la propriété white-space sur l'élément affichant le contenu de votre textarea:

white-space: pre-line;
4
OualidAj

À partir de React 16, un composant peut retourner un tableau d'éléments, ce qui signifie que vous pouvez créer un composant comme celui-ci:

export default function NewLineToBr({children = ""}){
  return children.split('\n').reduce(function (arr,line) {
    return arr.concat(
      line,
      <br />
    );
  },[]);
}

que vous utiliseriez comme ceci:

<p>
  <NewLineToBr>{address}</NewLineToBr>
</p>
1
Pete Hodgson

La proposition précédente de Pete avec composant autonome est une excellente solution bien qu’il manque une chose importante. Répertorie les besoins clés . Je l'ai ajusté un peu et ma version (sans les avertissements de la console) ressemble à ceci:

const NewLineToBr = ({ children = '' }) => children.split('\n')
  .reduce((arr, line, index) => arr.concat(
    <Fragment key={index}>
      {line}
      <br />
    </Fragment>,
  ), [])

Il utilise React 16's Fragments

1
webit

Amour version webit. Je ne connaissais pas le composant Fragment, c'est tellement utile. Pas besoin d'utiliser la méthode réduire cependant. La carte est suffisante. De plus, la liste a besoin de clés pour réagir, mais il est déconseillé d’utiliser l’index de la méthode itérative. Eslint a continué à écraser cela dans mon avertissement jusqu'à ce que j'ai eu le bug de confusion. Donc, cela ressemblerait à ceci: 

const NewLine = ({ children }) =>
   children.split("\n").map(line => (
    <Fragment key={uuidv4()}>
      {line}
      <br />
    </Fragment>
  ));
0
Handle