简体   繁体   English

反应,我如何嵌入 <br/> 在jsx表达式中

[英]React, how do I embed <br/> in jsx expressions

I'm rendering different texts depending on a given variable, and I simply want to render 我根据给定的变量渲染不同的文本,我只想渲染
at a particular variable within h2 tag. 在h2标签内的特定变量处。

I tried using regex \\r and \\n (and the combination) to render, but it hasn't work. 我尝试使用正则表达式\\ r和\\ n(以及组合)进行渲染,但是它不起作用。


render() {

  let {tracker} = this.props, headline;

  switch(tracker){
    case 1:
     headline = 'That is amazing!'
     break;
    case 2:
     headline = 'Too bad.<br />Try again'
     break;
  }

  return(
    <h2>{headline}</h2>
  )
}

The issue with your example is that the <br /> is inside a string, so React will read it as a string and won't turn the <br /> into a real HTML element. 您的示例的问题在于<br />位于字符串中,因此React会将其读取为字符串,并且不会将<br />转换为真正的HTML元素。

The natural solution would be to concat the string to an actual JSX <br /> : 自然的解决方案是将字符串连接到实际的JSX <br />

headline = 'Too bad.' + <br /> + 'Try again';

But this won't work as we hope it might. 但这不会像我们希望的那样起作用。 The result will be Too bad.[object Object]Try again . 结果将是Too bad.[object Object]Try again This is because JSX is just syntactical sugar that compiles down to React.createElement('br') , and this function returns an object that represents a React Node. 这是因为JSX只是语法糖,可以编译为React.createElement('br') ,并且此函数返回表示React节点的对象。

You could use a React Fragment instead of a string in the second case: 在第二种情况下,您可以使用React Fragment而不是字符串:

render() {

  let {tracker} = this.props, headline;

  switch(tracker){
    case 1:
     headline = 'That is amazing!'
     break;
    case 2:
     headline = <>Too bad.<br />Try again</>
     break;
  }

  return(
    <h2>{headline}</h2>
  )
}

This JSX compiles down to something like React.createElement(React.Fragment, [], ['Too bad.', React.createElement('br'), 'Try again']); 该JSX可以编译成类似React.createElement(React.Fragment, [], ['Too bad.', React.createElement('br'), 'Try again']); This bit isn't too relevant to your question but I think it's good to know what JSX is doing under the hood. 这一点与您的问题不太相关,但是我认为最好了解JSX在后台进行的工作。

It seems like you want to render a different headline depending on the tracker value passed from the parent. 似乎您想根据从父级传递的跟踪器值来渲染不同的标题。

Analysis 分析

Let's see what's wrong with the code below. 让我们看看下面的代码有什么问题。

render() {

  let {tracker} = this.props, headline;

  switch(tracker){
    case 1:
     headline = 'That is amazing!'
     break;
    case 2:
     headline = 'Too bad.<br />Try again'
     break;
  }

  return(
    <h2>{headline}</h2>
  )
}

First of all, the declaration of this.props, headline seems very unintuitive. 首先,声明this.props, headline似乎很不直观。
Let's separate it into two. 让我们将其分成两个部分。

let headline;
let { tracker } = this.props;

Now, switch checks for the condition and try to assign the headline value. 现在, switch检查条件,并尝试分配标题值。

  switch(tracker){
    case 1:
     headline = 'That is amazing!'
     break;
    case 2:
     headline = 'Too bad.<br />Try again'
     break;
  }

Now that's problematic because when you return <h2>{headline}</h2> , what React is expecting is an element . 现在这是有问题的,因为当您返回<h2>{headline}</h2> ,React期望的是一个element

The valid expression can be of string, number, or another JSX element. 有效表达式可以是字符串,数字或另一个JSX元素。

The case 1, is OK, because it's a string. 情况1可以,因为它是一个字符串。
But the reason you are having trouble with case 2 is because <br /> is part of a string, thus React considers it a string (and try to decode it). 但是您遇到情况2的原因是因为<br />是字符串的一部分,因此React将其视为字符串(并尝试对其进行解码)。

So what can we do? 所以,我们能做些什么?

Solution(s) 解决方案

You can convert the case 2 into an element by getting rid of quotes, and wrapping it into an element. 您可以通过删除引号并将其包装到元素中来将案例2转换为元素。 You can use any elements such as div , React.Fragmenet (<>/). 您可以使用任何元素,例如divReact.Fragmenet (<> /)。

  switch(tracker){
    case 1:
     headline = 'That is amazing!'
     break;
    case 2:
     headline = <>Too bad.<br />Try again</>
     // or use "div" or other element.
     // headline = <div>Too bad.<br />Try again</div>
     break;
  }

Another way is to render it dangerously . 另一种方法是使其变得危险 You should never do this unless you know what you are doing. 除非您知道自己在做什么,否则绝对不要这样做。 I won't go further as this is probably not what you want. 我不会更进一步,因为这可能不是您想要的。

Additional tip. 额外提示。

The code you used using switch is what's called an "imperative" code. 您使用switch使用的代码称为“命令式”代码。 (You specify "how" the component should work). (您指定组件应如何工作)。
But React is declarative in nature, and you tell "what" the component should do. 但是React本质上是声明性的,您可以告诉组件应该做什么。

So let's fix it up a bit and make it React-like. 因此,让我们对其进行修复,使其类似于React。

render() {
  // 👇 tracker is not changed, so declare it as `const`, which is a better practice.
  const {tracker} = this.props

  // You tell React what you want to do.
  // When the tracker value is 1, show 'That's amazing!', 
  // When it's two, show the sympathy.
  return(
    <h2>
      {tracker === 1 && 'That is amazing!}
      {tracker === 2 && <>Too bad.<br />Try again</>}
    </h2>
  )
}

The code above does the same thing, but you basically tell what to do, instead of how it should render. 上面的代码执行相同的操作,但是您基本上会说出要做什么,而不是应该如何呈现。

Or you can simply go further but I guess this is enough for a tip. 或者,您可以走得更远,但我想这足以给小费。

In situations when you receive strings with a format that you can control (ie localization files, or fetched from server side message) and you want the output with line-break, you can use: 如果您收到的字符串具有可以控制的格式(即本地化文件或从服务器端消息中提取),并且希望输出带有换行符,则可以使用:

<div style={{whiteSpace: 'pre-wrap'}}>{'Too bad.\nTry again'}</div>

\\n and white-space: pre-wrap does the trick. \\ n和空格:预先包装即可解决问题。

在这种情况下,我个人使用Fragment或一些不会产生特殊问题的元素(例如span

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM