Reputation: 685
I am rendering a few data items in a row, separated by bullets, sometimes omitting these strings if they aren't available/applicable.
const items = [
age !== null && `age ${age}`,
nationality && countryName(nationality),
/* ... */
];
return <Text>{items.filter(x=>x).join(' • ')}</Text>;
I now want to make the age number bold, and so I've replaced the string in the array with a fragment:
[age !== null && (<Fragment>age <Text style={styles.ageNumber}>{age}</Text></Fragment>)]
Reassembling it, I can no longer do join
, as that only works on strings. Instead, I've interspersed it with string literals,
const intersperse = (xs, sep) => xs.flatMap((x, i) => (i > 0 ? [sep, x] : [x]));
return <Text>{intersperse(items.filter(x => x), ' • ')}</Text>;
Now that I am passing an array to React, rather than combining it in JavaScript, I get the warning that each child in my array needs a key. How do I handle this nicely, other than by raising more warnings by using the index as the key?
Upvotes: 0
Views: 1435
Reputation: 1167
If you have no unique identifier in your array, it's simply a matter of creating a unique index of your choice. Personally, I'd do something like this:
const intersperse = (xs, sep) => xs.flatMap((x, i) => (i > 0 ? [sep, x] : [x]));
return <Text key={`user-info-${Math.random()}`}>{intersperse(items.filter(x => x), ' • ')}</Text>;
Naturally, Math.random()
does not necessarily give you a unique number but would usually suffice in the majority of cases. However, if you want to be 100% sure you get a unique key, you could use something like Lodash's uniqueId
method instead:
import { uniqueId } from 'lodash/uniqueId';
const intersperse = (xs, sep) => xs.flatMap((x, i) => (i > 0 ? [sep, x] : [x]));
return <Text key={uniqueId('user-info-')}`}>{intersperse(items.filter(x => x), ' • ')}</Text>;
Hope this helps.
EDIT:
Simpler solution as discussed in comments: https://jsfiddle.net/jthcys8v/1/
There's no reason to add things to an array as you're just complicating things. In my opinion this is a much cleaner solution. You could expand on this and call other methods to actually render the Age
and Nationality
elements, e.g.
<div>
{userInfo.age && this.renderAge()}
{userInfo.nationality && this.renderNationality()}
</div>
Upvotes: 0
Reputation: 1661
You don't need to create array of nodes, instead you can use combination of reduce
and Fragment
to create final node and just forget about keys.
This technique is especially useful when you don't have data which has unique keys.
Solution here 👇
Upvotes: 2