2
votes

I have a string I need to parameterise like 'Hello {name}, how are you?'. I want to replace the curly braces and text inside with a variable then render it in my React Component but I also need that text to be highlighted and bold by wrapping the variable text in a span/strong tag e.g. of desired final result

Hello <span class="text-info"><strong>Dave</strong></span>, how are you?

I'm using React/JSX and I know how to replace the curly braces and text inside them using String.replace then render it e.g.

// This string with the placeholder curly braces would be received from an API call to a server. Only set here for demonstrative purposes
let string = 'Hello {name}, how are you?' 
let name = 'Dave' // Likewise would not be set manually here, it's held in a redux store
let greeting = string.replace(/{(.*?)}/, name);

// This renders the greeting as you'd expect e.g. <p>Hello Dave, how are you?</p>
return (
   <p>{greeting}</p>
)

However, if I try and replace the curly braces with a span element it renders incorrectly with [object Object] instead of my parameter

// ...rest of stateless Component.jsx
let greeting = string.replace(/{(.*?)}/, <span>{name}</span>);

// This renders the HTML <p>Hello [object Object], how are you?</p>
return (
   <p>{greeting}</p>
)

I think it must be something to do with React escaping something but to be honest that's a total guess. Any ideas how I can achieve the desired functionality?

JSFiddle: https://jsfiddle.net/ExoticChimp1990/o69ymt7q/

3
Is there a reason you're using String.replace and not doing something like this? jsfiddle.net/e851a1ua - erichardson30
it's because the string and the name variables come from the server in separate calls. So the name is held in a redux store on a user object. And the text is also stored on the server in the db with the placeholder. So I need to replace the placeholder with the user info from the store. question clarified - ExoticChimp
After transpiling, <span>{name}</span>,will be replaced with the result of React.createElement("span", null,{name}) which returns an object, that's why your resulting string is showing as [object Object]. - slugo
@user1858268 yeah i thought something like that might be happening, do you know any alternative strategies for achieving the desired functionality? - ExoticChimp
You could replace by "<span>" + {name} + "</span>" for example, and then render using setInnerHtml. But there probably are other ways. - slugo

3 Answers

3
votes

You can try replacing by a string containing raw html tags and then render your div using dangerouslySetInnerHTML.

var greeting = textToEnhance.replace(/{(.*?)}/, '<span>'+this.props.name+'</span>'); 

return <div dangerouslySetInnerHTML={{__html:greeting}}></div>;
2
votes

BTW, you can use the formatting of ES6 e.g.

const name = "David";
const myHTML = `Hello ${name}, how are you?`;

Note: these are not single quotes, but ` symbols. This symbol called as "grave accent" character

I understand your templates come from a server, so you cannot directly use the method above.

However, using RegExp such as /\$\{(\w+?)\}/g (click to expirement with this RegExp) you can parse and iterate through all your variable names e.g.

var newString = templateString.replace(/(\$\{\w+?\})/g, function(match, p1, offset, str) {
  var matches = /\$\{(\w+?)\}/.exec(p1);
  var variableName = matches[1];
  return variables[variableName]
    ?variables[variableName]
    :console.error("Variable " + variableName + " is undefined in offset " + offset);
});

When variables is a predefined object containing your variables as key values pairs and templateString contains your template (optionally from a server).

0
votes

The second argument you are using in string.replace is not correct. name variable inside curly braces means, a javascript object with name key and value as that in name variable.

let greeting = string.replace(/{(.*?)}/, '<span><strong>'+name+'</strong></span>');

I am sorry, as I didnt enter the string above as code, it ommited the tags. Now they must be visible.