web-dev-qa-db-fra.com

Rendu liste de liens séparés par des virgules

J'essaie de produire une liste de liens séparés par des virgules et voici ma solution.

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

    var tags = [],
        tag;

    for (var i = 0, l = item.tags.length; i < l; i++) {
      if (i === item.tags.length - 1) {
        tag = <span><Tag key={i} tag={item.tags[i]} /></span>;
      } else {
        tag = <span><Tag key={i} tag={item.tags[i]} /><span>, </span></span>;
      }
      tags.Push(tag);
    }

    return (
      <tr>
        <td>
          {item.name}
        </td>
        <td>
          {tags}
        </td>
      </tr>
    );

  }
});

Je me demandais s'il y avait une meilleure façon, plus propre, d'accomplir cela?

Merci

26
Nick

À la Khan Academy, nous utilisons un assistant appelé intersperse pour ceci:

/* 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]]);
}

ce qui vous permet d'écrire du code comme:

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

Simplement

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


Dans React 16, cela peut être encore plus simple:

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

Ou simplement écrivez les éléments de la liste sur une liste non ordonnée et utilisez 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>
    );

  }
});

Et le 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;
}
7
i_like_robots
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>
);
1
Sebastien Lorber

Voici une solution qui autorise <span>s et <br>s et les fichiers indésirables en tant que séparateur:

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);
}

Il filtre également les éléments du tableau falsey. J'ai utilisé cela pour formater des adresses, où certains champs d'adresse ne sont pas renseignés.

Il utilise des fragments pour éviter les avertissements concernant les clés manquantes.

0
mpen

La solution sans balises supplémentaires

reduce est excessif ici et la fonction optimale à utiliser est (techniquement) flatMap (ou chain en Ramda). Malheureusement, JS n'en fournit pas (encore).

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

génère quelque chose comme

Fonction • Type de fonction • Fonction d'ordre supérieur • Application partielle

P.S.

pour Ramda c'est R.addIndex(R.chain) au lieu de flatMap ci-dessus.

0
Ivan Kleshnin

Manière la plus facile de faire

    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>
        )
    }
0
pareshm

Un simple:

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