如何使用JSX和Lodash重复一个元素n次

180

我正在使用React/JSX和Lodash来完成我的应用程序。

我需要根据条件重复某个元素特定次数,我应该怎么做?

这是该元素:

<span className="busterCards">♦</span>;

我是这样进行赋值的:

let card;
if (data.hand === '8 or more cards') {
  card = <span className='busterCards'>♦</span>;
}

所以在这种情况下,我需要重复元素8次。使用 Lodash 应该采取什么过程?


5
这段代码的翻译是:new Array(8).join('<span className="busterCards">♦</span>'); - Ram
1
@Vohuman提出的解决方案是完成工作的非常干净的方式。在lodash文档中未定义可比较的函数。 - dbeg
2
@Vohuman它会生成一个字符串,而OP想使用JSX语法创建DOM。 - pawel
1
@Vohuman 这很奇怪,但我正在渲染整个字符串。 - StillDead
1
@pawel 你说得对,你知道我该怎么做吗? - StillDead
链接 - https://dev59.com/pV8e5IYBdhLWcg3whqzl - vsync
12个回答

506

在没有使用任何外部库的情况下,完成此操作的最短路径

const n = 8; // Or something else

[...Array(n)].map((e, i) => <span className="busterCards" key={i}></span>)

15
非常好的答案,适用于不使用 Lodash 的用户!值得指出的是,它需要 ES6 功能(尽管我认为在问题中使用 let 已经暗示了这一点)。 - pseudoramble
7
对于使用 Typescript 2+ 的用户,这会编译成 Array(3).slice().map(...),这不会得到相同的结果。请参考下面 @Jian 的答案进行替代。 - Pierre vDEV
6
为什么不能只用Array(n).map((e, i) => <span className="busterCards" key={i}>♦</span>)呢? - Kevin Wang
15
因为你的建议会创建一个长度为8的空数组,而不是由8个未定义项组成的数组。在前者上进行迭代将无法正常工作。将其放入控制台中查看区别。 - Darbio
1
@Garrett,该规则的文档明确指出不要使用规则“如果项目没有独特之处”——这在这里确实是字面意义上的情况。因此,在这里禁用linter规则你不应该感到难过。 - Waiski
显示剩余4条评论

65

没有使用Lodash或ES6扩展语法的解决方案:

Array.apply(null, { length: 10 }).map((e, i) => (
  <span className="busterCards" key={i}>
    ♦
  </span>
));

这看起来更加清晰,但是在迭代次数超过126000左右时,我会收到“调用栈大小超出最大限制”的错误提示(至少在Chrome桌面版中)。 - jave.web
我遇到了一个同事使用这段代码,一开始看到他使用Array.apply循环特定次数并不直观。如果未来的开发人员将阅读您的代码,我个人会首先考虑其他更直观的解决方案。 - Logan Cundiff
1
很抱歉听到这个消息。该解决方案旨在尽可能少地使用依赖项。我建议您的同事通过将其制作成可重用函数并使用类似“times”的明智名称来提高可读性。 - Weihang Jian

45

这是您需要的:

let card = [];
_.times(8, () => {
  card.push(<span className="busterCards"></span>);
});

你可能想要为每个元素添加key属性,这样React就不会抱怨缺少key属性了:


let card = [];
_.times(8, (i) => {
  card.push(<span className="busterCards" key={i}>♦</span>);
});

了解有关.times的更多信息,请参见此处:https://lodash.com/docs#times


2
我正在尝试将其分配给 let card,但它没有重复元素。 - StillDead
1
或者简单地写成 const card = _(8).times(idx => <span key=${idx} className="busterCards">♦</span>); - tokland
1
你也可以简单地返回 _.times(.....) 来渲染元素。确保你在内部也使用 return (<Element></Element>)。 - msqar

33

没有使用 Lodash 实现

<section>
      {Array.from({ length: 10 }, (_, i) => <span key={i}>Your text</span>)}
 </section>

这是如何工作的?

Array.from() 有两种用法:

  1. 将类数组结构转换为数组。例如,我们可以使用 Array.from() 将 Map 转换为数组。

    const map = new Map([ [1, 2], [3, 4], [4, 5] ])

    console.log(Array.from(map)) //得到一个数组 - [[1, 2], [3, 4], [4, 5]]

  2. 创建一个数组并填充值(当需要创建包含更多元素的数组时非常实用)

Array.from() 接受一个对象和一个回调函数。

Array.from({ length: 7 }, (() => 10)) // 得到 [10,10,10,10,10,10,10]

我们可以利用回调函数中的索引(第二个参数)来提供独特的数组元素

Array.from({ length: 4 }, ((_, i) => i + 1)) // [1,2,3,4]


3
虽然这段代码可以回答问题,但是提供关于为什么和/或如何回答问题的额外背景信息会提高它的长期价值。 - Al Foиce ѫ

16

我正在使用这个,对我来说很有效。

[...Array(10)].map((elementInArray, index) => ( 
    <div key={index}>
      Text in Loop
    </div>
))

7
使用_.times函数:https://jsfiddle.net/v1baqwxv/
var Cards = React.createClass({
    render() {
        return <div>cards {
          _.times( this.props.count, () => <span></span> )
        }</div>;
    }
});

6
你可以这样做(不使用lodash):
var numberOfCards = 8; // or more.

if (data.hand >= numberOfCards) {
    var cards = [];

    for (var i = 0; i < numberOfCards; i++) {
        cards[i] = (<span className="busterCards"></span>);
    }
}

6

在没有任何外部库的情况下,有几种简单直接的选项来实现这一点(2021年):

// straight forward but without key index. Not so good for react but work fine with worning 
Array(X).fill(<span className="busterCards">♦</span>)
// with index
Array(X).fill().map((v,i)=> <span className="busterCards">♦</span>)

Array.from( Array(X), (v,i) => <span key={i} className="busterCards">♦</span> )
// same thing basically 
Array.from( {length:X}, (v,i) => <span key={i} className="busterCards">♦</span> )

[...Array(3)].map( (_,i)=> <span key={i} className="busterCards">♦</span> )

3

您可以创建一个数组,其中包含需要呈现的任意数量的项,然后通过对数组进行映射来呈现所需数量的元素。

const totalItems = 8;

const items = new Array(totalItems).fill(null);


// .... then
return (
    {items.map((_, idx) => <span className="busterCards" key = {idx}>♦</span>)}
);

1

今天我在做这个的时候遇到了这个问题,我认为更好的方法是不创建数组,也不使用任何包。这就是递归。


const YourComp = ({ n }) => {
  if (n == 0) {
    return null;
  }
  return (
    <div className="py-8">
     do something
      <YourComp n={n - 1} />
    </div>
  );
};

酷吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接