使用 Ramda `range` 进行复制,但需要每 3 次插入一次(React)

Using Ramda `range` to duplicate, but need to interject at every 3rd (React)

我目前正在使用 Ramda 为记录的每个 perk 实例输出 Material-UI CheckCircle。它们最多可以有 18 个,所以我也用它来继续计数 past the perk 到最大值 18 以显示潜在的最大值。

{R.range(0, this.props.perkProgress).map(() => <CheckCircle key={uid()} /> )}
            {R.range(this.props.perkProgress, 18).map(() => <CheckBoxOutline key={uid()} /> )}

这两行完美地工作,但是我还需要在每个 'third' 行之后插入一些东西 - 而是一个框,或者一个复选标记。因为我不相信我可以用 Ramda 做,我怎么能用普通的 JS 感觉来写这个(或者把它包装在一个函数中;两者之一)来获得我需要的输出?

this.props.perkProgress 始终是 0 到 18 之间的整数。

如果他们有“5”,我希望有 5 个复选标记和 13 个空方块。

添加一个 terrible drawing 当前功能部分,以及所需的最终结果:

这可以使用 Ramda 实现,方法是首先使用 R.splitEvery then adding the separator between each split list using R.intersperse and finally joining the split lists back together with R.unnest 分割元素列表。

(n.b。为了简洁起见,我用下面的字符串替换了你的 JSX)

// inserts `sep` between every `n` elements of a list `xs`
const separateEvery = (sep, n, xs) =>
  R.unnest(R.intersperse([sep], R.splitEvery(n, xs)))

const genElements = (totalSize, progress) =>
  separateEvery('Separator', 3, R.concat(
    R.repeat('CheckCircle', progress),
    R.repeat('CheckBoxOutline', totalSize - progress)
  ))

console.log(genElements(18, 7))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>


更新以回应以下评论


向每个生成的元素添加键的一种方法是使用 React.cloneElement.

映射每个元素
const genElementsWithKey = R.pipe(
  genElements,
  R.addIndex(R.map)((el, key) => React.cloneElement(el, {key}))
)

或者,如果您出于某种原因不想使用 cloneElement,那么您可以使用 R.zipWith 换出 R.intersperse,以创建一个唯一的分隔符元素以在每个组之间插入元素数。

const createCircle = _ => '<CheckCircle key={uid()} />'
const createCheckBox = _ => '<CheckBoxOutline key={uid()} />'
const createSeparator = _ => '<Separator key={uid()} />'

const genElements = (totalSize, progress) => {
  const splitEls = R.splitEvery(3, R.concat(
    R.map(createCircle, R.range(0, progress)),
    R.map(createCheckBox, R.range(progress, totalSize))
  ))
  
  const firstSplitGroup = splitEls[0]
  const remainingSplitGroups = R.tail(splitEls)
  
  // create a list of separators matching the number of elements in remainingSplitGroups
  const separators = R.map(createSeparator, R.range(0, remainingSplitGroups.length))
  
  return R.concat(
    // keep the first split group as is
    firstSplitGroup,
    // prepend a separator to each of the remaining split groups
    R.unnest(R.zipWith(R.prepend, separators, remainingSplitGroups))
  )
}

console.log(genElements(18, 7))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>