You can also use reduce to insert the separator between every element of the array:
render() {
let myArray = [1,2,3];
return (
<div>
{
myArray
.map(item => <div>{item}</div>)
.reduce((acc, x) => acc === null ? [x] : [acc, ' | ', x], null)
}
</div>
);
}
or using fragments:
render() {
let myArray = [1,2,3];
return (
<div>
{
myArray
.map(item => <div>{item}</div>)
.reduce((acc, x) => acc === null ? x : <>{acc} | {x}</>, null)
}
</div>
);
}
Answer from Bless on Stack OverflowYou can also use reduce to insert the separator between every element of the array:
render() {
let myArray = [1,2,3];
return (
<div>
{
myArray
.map(item => <div>{item}</div>)
.reduce((acc, x) => acc === null ? [x] : [acc, ' | ', x], null)
}
</div>
);
}
or using fragments:
render() {
let myArray = [1,2,3];
return (
<div>
{
myArray
.map(item => <div>{item}</div>)
.reduce((acc, x) => acc === null ? x : <>{acc} | {x}</>, null)
}
</div>
);
}
You can also do it by combining .reduce and React fragments.
function jsxJoin (array, str) {
return array.length > 0
? array.reduce((result, item) => <>{result}{str}{item}</>)
: null;
}
function jsxJoin (array, str) {
return array.length > 0
? array.reduce((result, item) => <React.Fragment>{result}{str}{item}</React.Fragment>)
: null;
}
const element = jsxJoin([
<strong>hello</strong>,
<em>world</em>
], <span> </span>);
ReactDOM.render(element, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.1/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
A simple solution is to use reduce() without second argument and without spreading the previous result:
class List extends React.Component {
render() {
<div>
{this.props.data
.map(t => <span>{t}</span>)
.reduce((prev, curr) => [prev, ', ', curr])}
</div>
}
}
Without second argument, reduce() will start at index 1 instead of 0, and React is perfectly happy with nested arrays.
As said in the comments, you want to only use this for arrays with at least one item, because reduce() without second argument will throw with an empty array. Normally this should not be a problem, since you want to display a custom message saying something like 'this is empty' for empty arrays anyway.
Update for Typescript
You can use this in Typescript (without type-unsafe any) with a React.ReactNode type parameter on .map():
class List extends React.Component {
render() {
<div>
{this.props.data
.map<React.ReactNode>(t => <span>{t}</span>)
.reduce((prev, curr) => [prev, ', ', curr])}
</div>
}
}
You can use reduce to combine multiple elements of an array:
React.createClass({
render() {
<div>
this.props.data
.map(t => <span>t</span>)
.reduce((accu, elem) => {
return accu === null ? [elem] : [...accu, ',', elem]
}, null)
</div>
}
})
This initializes the accumulator with null, so we can wrap the first item in an array. For each following element in the array, we construct a new array that contains all previous elements using the ...-operator, add the separator and then the next element.
Array.prototype.reduce()
How to using array.prototype.join in reactjs - javascript
How to using array.prototype.join in reactjs
How to join elements in an array within a state variable?
Insert item between every other item in array similar to Array.join
I've got an array in a state variable and am trying to join the elements into one string. Here's a stripped down version of what I'm trying to do:
I've tried this:
const [problem, setProblem] = useState(["leaving it all behind", "no tears not time"])
const change = () => {
console.log(problem)
setProblem(problem.join())
console.log("joined", problem)
}and this
const [problem, setProblem] = useState(["leaving it all behind", "no tears not time"])
const change = () => {
console.log(problem)
const solution = problem.map(arr => arr.join(','))
console.log("joined", problem, solution)
}
They both don't work. I'm trying to get to the point where problem is "leaving it all behind no tears not time"
You could use reduce without the initialValue argument:
a.reduce((acc, val) => [].concat(acc, delimiter, val));
This requires special care when a is an empty array. If that needs to be supported, then:
a.length ? a.reduce((acc, val) => [].concat(acc, delimiter, val)) : a;
Addendum
I just found out that TypeScript only allows the second argument of reduce to be omitted when reduce will return the same type as the array elements. Here we want to return a different type (T[] instead of T), yet start out with an implicit T initial value. Not possible.
So this restriction kills the beauty of the above JavaScript solution, as now we have to provide the second argument:
a.reduce<T[]>((acc, val) => acc.concat(delimiter, val), []).slice(1);
And with additional type specifications for the callback parameters:
a.reduce<T[]>((acc: T[], val: T) => acc.concat(delimiter, val), []).slice(1);
Maybe these are nice minor adjustments:
const joinByDelimiterButKeepAsArray = <T, D>(arr: T[], delimiter: D): (T | D)[] => {
return arr.flatMap((item, i) => i == 0 ? item : [delimiter, item])
}