4

I am learning React and have run into the following situation:

I have a string variable that I am passing as a prop to different components to be rendered by JSX.

When the component and its sub-components are rendered, the string does not render html special characters, instead rendering the character code as text.

How can I get the variable to render as html?

Here is the code for a component that works completely, except that the tempUnitString variable renders as &deg; K, while the <th> below renders its units as ° K.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import Chart from '../components/chart';
import GoogleMap from '../components/google_map'

class WeatherList extends Component {
  renderWeather(cityData, tempUnits){
    const name = cityData.city.name;
    const id = cityData.city.id;
    const humidity = cityData.list.map(weather => weather.main.humidity);
    const pressure = cityData.list.map(weather => weather.main.pressure);
    const { lon, lat } = cityData.city.coord;
    let temp = cityData.list.map(weather => weather.main.temp);
    if (tempUnits === "K"){
        temp = cityData.list.map(weather => weather.main.temp);
    } else if (tempUnits === "F"){
        temp = cityData.list.map(weather => weather.main.temp * 9/5 - 459.67);
    } else {
        temp = cityData.list.map(weather => weather.main.temp - 273.15);
    }
    let tempUnitString = "&deg; " + tempUnits;

    return (
      <tr key={ id }>
        <td><GoogleMap lat={ lat } lon={ lon } /></td>
        <td>
          <Chart color="red" data={ temp } units={ tempUnitString } />
        </td>
        <td>
          <Chart color="green" data={ pressure } units=" hPa" />
        </td>
        <td>
          <Chart color="orange" data={ humidity } units="%" />
        </td>
      </tr>);
  }
  render() {
    const tempUnits = this.props.preferences.length > 0 ? this.props.preferences[0].tempUnits : "K";

    return (
      <table className="table table-hover">
        <thead>
          <tr>
            <th>City</th>
            <th>Temperature (&deg; { tempUnits })</th>
            <th>Pressure (hPa)</th>
            <th>Humidity (%)</th>
          </tr>
        </thead>
        <tbody>
          { this.props.weather.map( item => this.renderWeather(item,tempUnits) ) }
        </tbody>
      </table>
    );
  }


}

function mapStateToProps({ weather, preferences }){// { weather } is shorthand for passing state and { weather:state.weather } below
  return { weather, preferences }; // === { weather:weather }
}

export default connect(mapStateToProps)(WeatherList);

UPDATE

Using the documentation passed to me by @James Ganong I set up a boolean prop on the subcomponent isTemp and based on that created a JSX variable.

The subcomponent (minus includes and func definitions) looks like this:

export default (props) => {
  let tempDeg = '';
  if (props.isTemp){
    tempDeg = <span>&deg;</span>;
  }
  return (
    <div>
      <Sparklines height={ 120 } width={ 100 } data={ props.data }>
        <SparklinesLine color={ props.color } />
        <SparklinesReferenceLine type="avg" />
      </Sparklines>
      <div>{ average(props.data)} { tempDeg }{ props.units }</div>
    </div>
  );
}

The call to it looks like this:

<Chart color="red" data={ temp } units={ tempUnits } isTemp={ true } />

2 Answers 2

4

React actually has a page that addresses this and some other potential solutions (using unicode characters, saving the file as utf8, using dangerouslySetInnerHtml): jsx-gotchas


Another option is to create a simple, reusable Temp component that has types you pass it:

const TEMP_C = 'C';
const TEMP_K = 'K';

const Temp = ({ children, unit }) => <span>{children}&deg;{unit}</span>;

const App = () => (
  <div>
    <p>Temperature 1: <Temp unit={TEMP_K}>25</Temp></p>
    <p>Temperature 2: <Temp unit={TEMP_C}>25</Temp></p>
  </div>
);

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for this information. I marked it as the solution because you found documentation that I couldn't. haha. Ultimately, I need to customize this approach and use some conditional logic because I am running the temperature through a generic component that creates sparklines for temperature and other datasets. I'll add my final solution as an additional solution below.
I wound up just updating the question with the solution.
Cheers - two things: 1. if you need to pass a prop as true (like isTemp={true}) you actually don't need the ={true} part, just by setting isTemp as an attribute (without the equals) it evals to true. 2. You could combine the if statement into the jsx instead of needing to use the tempDeg variable. ie replace { tempDeg } with {props.isTemp && (<span>&deg;</span>)}
Cheers to that as well!
0

Without string concatenation html symbols works as usual. For some reason, when you concatenate a symbol with a string, then the symbol isn't decoded and it's rended as characters.

You can workaround it as in the example below or use a plugin (html-entities for instance).

const App = () => <Child deg="&deg;" temp={25} />;
const Child = ({deg, temp}) => <div>{temp} {deg}</div>;

ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

4 Comments

Hi Jordan, The problem is that I want to pass the concatenated string into a separate component as a param. I would rather not have to put clunky conditional logic into the subcomponent, or create separate components just to handle this one case.
I checked out your approach, and the problem appears to be with the way that the string is being passed to the subcomponent
Perhaps a conversion from string variable to props property changes rendering behavior?
Here is described what's happening: reactjs.cn/react/docs/jsx-gotchas.html. Thanks to James' answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.