简体   繁体   中英

React render array of strings and JSX

I want to render JSX like the following:

<p>
    Some text with a <span> match </span> in it
</p>

My thought is to prepare data like this:

var text = ["Some text with a", <span>match</span>, "in it"]
return <p> {text} </p>

But this leads to problems with React keeping track of iterated children lacking keys.

Each child in an array or iterator should have a unique "key" prop.

Any idea how I could solve this problem?

Edit: to give some sense for how this is used, check out the following function stub:

/**
 * prepares string with JSX span tags to assist with highlighting of search result matches 
 * @param {string} name string to find the match within
 * @param {string} matchString the search query string that we are highlighting against
 * 
 * @returns {Array} an array containing characters and JSX for syntax highlighting
 */
export const matchHighlighting = (name, matchString) => {...}

I know the search query and the response text and want to display to the user highlights -- I essentially attempted to write a function that would interpolate the contents of a string with span tags where necessary, leaving me with an array similar to the example that I posted at the top.

This react issues thread kind of highlights the problem; sounds like it's a tough one that hasn't really found a good solution?

To solve the issue related to key, you need to put key attribute on each of the array elements. To do this, instead of

<p> {text} </p>

we need to iterate over the array, like this -

{text.map((el,index)=> {<p key={index}>{el}</p>})}

I've used @sophiebit's solution here. Seems working :)

 const matchHighlighting = (name, matchString) => { const re = new RegExp(`(\\\\b${matchString}+\\\\b)`, 'gi'); const parts = name.split(re); for (var i = 1; i < parts.length; i += 2) { parts[i] = <span className="match" key={i}>{parts[i]}</span>; } return <div>{parts}</div>; } const name = "Some text with a, match in it"; const matchString = "match"; class App extends React.Component { render() { return <div>{matchHighlighting(name, matchString)}</div>; } } ReactDOM.render(<App />, document.getElementById("root")); 
 .match { color: red; } 
 <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> 

Use React Fragments (introduced in React v16.0). Here is link to documentation

<React.Fragment>Some text with a <span>match</span> in it</React.Fragment>

ps Also why not just put inside of <p> ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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