4

I would like to use the join() method on a Javascript array, but I would like to join() with an HTML tag.

I want to do something like:

class Page extends React.Component {
    render() {
        <p>
           {this.props.the_form['candidate_ids'].map((val,idx) => {
               return this.getCandidateName(val);
           }).join('<br/>')}
        </p>
    }
}

It's escaping the tag and not rendering a new line.

I'm using React, Webpack, and Babel.

3
  • 2
    Escaping is performed by your framework, not JS itself. The line you provided generates a correct HTML. Please provide MCVE and details about the framework you use. Commented May 14, 2019 at 18:18
  • Thanks. I hadn't considered that it could be Babel or React. Commented May 14, 2019 at 18:25
  • 1
    This is really not the proper way to do this in react, you're already mapping the items, you should return simple html, not a string representation of html. See my answer below Commented May 14, 2019 at 18:52

2 Answers 2

9

I have to add this, since dangerouslySetInnerHTML and joining a long string isn't really the react way to do it, and a bit misleading. Plus, you're missing the key on your mapped items

//import Fragment
import { Fragment, Component } from "react"

class Page extends Component {
  const ids = this.props.the_form['candidate_ids'];
  render() {
    <p>
      {ids.map((val, idx) => {
        const name = this.getCandidateName(val);
        return (
          <Fragment key={`${name}${idx}`}>
            {name}
            {idx < ids.length - 1 && <br />}
          </Fragment>
        );
      })}
    </p>
  }
}

(updated to remove the trailing <br/>).

And here's a possible alternate version with no <br/>'s:

class Page extends Component {
  const ids = this.props.the_form['candidate_ids'];
  render() {
    <p>
      {ids.map((val, idx) => {
        const name = this.getCandidateName(val);
        return (
          <span key={`${name}${idx}`} style={{display: 'block'}}>
            {name}
          </span>
        );
      })}
    </p>
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Ah, this is much cleaner than what I've been doing. It is leaving a trailing break tag, which is why I was using join and map in the first place.
I'll probably add a ternary operator to deal with that, but it would be nice to have something cleaner.
Ah that's a snazzy solution to use a block. I had been using a comma, and wanted to make the list easier to read at a glance. I appreciate the use of Fragment and the bit of React I've learned now. Cheers!
This is nice! Very slight optimization could be swap {name}{idx < ids.length - 1 && <br />} for {!!idx && <br/>}{name}. The !! casts the idx number to a boolean, otherwize jsx will print it.
This also works when you replace <Fragment> with <> if you don't need a key.
2

Your code is fine. Assuming there is no framework at play here, the only thing I'd point out that you need to use innerHTML function

var mArray =[ 'line 1', 'line 2'];

document.body.innerHTML = mArray.map((val,idx) => { return `sometext: <strong>${val}</strong>`; }).join('<br/>')


update:

since you're using react, you need to use dangerouslySetInnerHTML

class Page extends React.Component {
    render() {
        const html = this.props.the_form['candidate_ids'].map((val,idx) => {
               return this.getCandidateName(val);
           }).join('<br/>')
        return <p dangerouslySetInnerHTML={{__html:html}}></p>
    }
}

But since you're using JSX, you shouldn't need to use strings and dangerouslySetInnerHTML. You can also just use jsx to compose your dom:

class Page extends React.Component {
    render() {
        const {the_form} = this.props;
        const dom = the_form['candidate_ids'].map((val,idx) => {
           return (
             <>
               {this.getCandidateName(val)}
               {idx+1 < the_form['candidate_ids'].length ? </br> : null}
             </>
           );
        }))
        return (<p>{dom}</p>);
    }
}

docs: https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

4 Comments

I'm using React and Babel.
I'm using JSX templates. I've edited my question to provide a better example.
Actually, this threw an error: Uncaught Error: props.dangerouslySetInnerHTML must be in the form {__html: ...}`
This is really bad form for react

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.