Rendering comma separated list of links

拜拜、爱过 提交于 2019-12-02 17:28:25

At Khan Academy we use a helper called intersperse for this:

/* intersperse: Return an array with the separator interspersed between
 * each element of the input array.
 *
 * > _([1,2,3]).intersperse(0)
 * [1,0,2,0,3]
 */
function intersperse(arr, sep) {
    if (arr.length === 0) {
        return [];
    }

    return arr.slice(1).reduce(function(xs, x, i) {
        return xs.concat([sep, x]);
    }, [arr[0]]);
}

which allows you to write code like:

var tags = item.tags.map(function(tag, i) {
    return <Tag key={i} tag={item.tags[i]} />;
};
tags = intersperse(tags, ", ");

Simply

{tags.map((tag, i) => <span key={i}>
    {i > 0 && ", "}
    <Tag tag={tag} />
</span>)}


In React 16 it can be done even more simpler:

{tags.map((tag, i) => [
    i > 0 && ", ",
    <Tag key={i} tag={tag} />
])}

Or simply write the list items to an unordered list and use CSS.

var Item = React.createComponent({
  render: function() {

    var tags = this.props.item.tags.map(function(i, item) {
      return <li><Tag key={i} tag={item} /></li>
    });

    return (
      <tr>
        <td>
          {this.props.item.name}
        </td>
        <td>
          <ul className="list--tags">
            {tags}
          </ul>
        </td>
      </tr>
    );

  }
});

And the CSS:

.list--tags {
    padding-left: 0;
    text-transform: capitalize;
}

.list--tags > li {
    display: inline;
}

.list--tags > li:before {
    content:',\0000a0'; /* Non-breaking space */
}
.list--tags > li:first-child:before {
    content: normal;
}
import React from 'react';
import { compact } from 'lodash';

// Whatever you want to separate your items with commas, space, border...
const Separator = () =>  { ... }; 

// Helpful component to wrap items that should be separated
const WithSeparators = ({ children, ...props }) => {

  // _.compact will remove falsey values: useful when doing conditional rendering
  const array = compact(React.Children.toArray(children));

  return array.map((childrenItem, i) => (
    <React.Fragment key={`${i}`}>
      {i > 0 && <Separator {...props} />}
      {childrenItem}
    </React.Fragment>
  ));
};

const MyPage = () => (
  <WithSeparators/>
    <div>First</div>
    {second && (<div>Maybe second</div>)}
    {third && (<div>Maybe third</div>)}
    <div>Fourth</div>
  </WithSeparators>
);

Here's a solution that allows <span>s and <br>s and junk as the separator:

const createFragment = require('react-addons-create-fragment');

function joinElements(arr,sep=<br/>) {
    let frag = {};
    for(let i=0,add=false;;++i) {
        if(add) {
            frag[`sep-${i}`] = sep;
        }
        if(i >= arr.length) {
            break;
        }
        if(add = !!arr[i]) {
            frag[`el-${i}`] = arr[i];
        }
    }
    return createFragment(frag);
}

It filters out falsey array elements too. I used this for formatting addresses, where some address fields are not filled out.

It uses fragments to avoid the warnings about missing keys.

The solution without additional tags

reduce is an overkill here and the optimal function to use is (technically) flatMap (or chain in Ramda). Unfortunately JS does not provide one (yet).

<p className="conceps inline list">
  {flatMap((concept, i) =>
    [concept, <span key={i} className="separator">&#8226;</span>]
  , lesson.concepts).slice(-1)}
</p>

generates something like

Function • Function type • Higher-order function • Partial application

P.S.

for Ramda it's R.addIndex(R.chain) instead of flatMap above.

Simple one:

{items.map((item, index) => (
    <span key={item.id}>
      {item.id}
      {index < items.length - 1 && ', '}
    </span>
 ))}

Easiest way to do

    const elementsArr = ["a","b,"c"];
    let elementsToRender = [] ;
    elementsArr.forEach((element, index) => {
        let elementComponent = <TAG className="abc" key={element.id}>{element}</TAG>
        elementsToRender.push(elementComponent);
        if(index !== (elementsArr.length - 1)){
            elementsToRender.push(", ");
        }
    });

    render(){
        return (
            <div>{elementsToRender}</div>
        )
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!