Javascript 如何包装在.map方法中重复的div

Javascript 如何包装在.map方法中重复的div,javascript,html,reactjs,loops,jsx,Javascript,Html,Reactjs,Loops,Jsx,如何在一个包含div的.map函数中封装一个返回 我知道我可以将整个.map包装在一个div中,但是在.map中我有两个不同的返回,因为我有一个if语句来检查graphQL类型名是否存在。我的问题是,我想将的输出包装在父div中,该父div包装整个div输出,以便在其上使用显示网格。如果在.map中没有具有两个不同返回的if语句,我可以这样做,因为我不想只包装 这是我的地图 {data.datoCmsProject.projectBlock.map(projectEntry => {

如何在一个包含div的.map函数中封装一个返回

我知道我可以将整个.map包装在一个div中,但是在.map中我有两个不同的返回,因为我有一个if语句来检查graphQL类型名是否存在。我的问题是,我想将的输出包装在父div中,该父div包装整个div输出,以便在其上使用显示网格。如果在.map中没有具有两个不同返回的if语句,我可以这样做,因为我不想只包装

这是我的地图

 {data.datoCmsProject.projectBlock.map(projectEntry => { 

      if (projectEntry.__typename === 'DatoCmsSingleProjectBlockContent') {
        return (
          <NewBlock key={projectEntry.id}> 

             Text Here

        </NewBlock>

        )
      }
      else{

        return (  // I want every div outputted here to be wrapped in one containing div

          <>

          <BlockGridWrapper>
            <BlockGrid key={projectEntry.id}>  
                <div>{projectEntry.titleOfGridSection}</div>
                <Img fluid={projectEntry.imageOfGridBlock.fluid} /> 
            </BlockGrid>
          </BlockGridWrapper>

          </>
        )

      }

  })}
所以我希望它最终的格式如下所示

<div>
  blockgridwrapper,
  blockgridwrapper
</div>
newblock,
<div>
  blockgridwrapper
</div>
newblock,
newblock,
newblock,
<div>
  blockgridwrapper,
  blockGridwrapper,
  blockGridwrapper
</div> 
第二个答案是我的回答

因此,根据相同的答案,这里是包装数据的console.log

0: Array(3)
0: {__typename: "DatoCmsSingleProjectBlockContent", id: "DatoCmsSingleProjectBlockContent-2018663-en", titleOfSection: "About Mussels", descriptionOfImage: "<h1><b>Heading 1</b></h1><p><span style="font-weig…DO: Anders and Riel Style</span></p></blockquote>", descriptionToggle: true, …}
1: {__typename: "DatoCmsSingleProjectBlockContent", id: "DatoCmsSingleProjectBlockContent-2018670-en", titleOfSection: "Test Title on top", descriptionOfImage: "<h1><b>Heading 1</b></h1><p><span style="font-weig…can see a list of things we did below.</span></p>", descriptionToggle: true, …}
2: {__typename: "DatoCmsSingleProjectBlockContent", id: "DatoCmsSingleProjectBlockContent-2018672-en", titleOfSection: "", descriptionOfImage: "", descriptionToggle: true, …}
length: 3
__proto__: Array(0)
1: Array(4)
0: {__typename: "DatoCmsProjectBlockGrid", id: "DatoCmsProjectBlockGrid-2043741-en", titleOfGridSection: "Test", imageOfGridBlock: {…}}
1: {__typename: "DatoCmsProjectBlockGrid", id: "DatoCmsProjectBlockGrid-2043742-en", titleOfGridSection: "Test #2", imageOfGridBlock: {…}}
2: {__typename: "DatoCmsProjectBlockGrid", id: "DatoCmsProjectBlockGrid-2043743-en", titleOfGridSection: "Test #3", imageOfGridBlock: {…}}
3: {__typename: "DatoCmsProjectBlockGrid", id: "DatoCmsProjectBlockGrid-2043744-en", titleOfGridSection: "Test #4", imageOfGridBlock: {…}}
现在如果我用下面的代码做嵌套映射

wrappedData.map(list => {
        return (
          <div>
            {list.map(l =>
              l._typeName === "DatoCmsSingleProjectBlockContent" ? (
                <NewBlock >text1</NewBlock>
              ) : (
                <BlockGridWrapper>
                  text2
                </BlockGridWrapper>
              )
            )}
          </div>
        );
      })
我得到了下面的html输出,但是根据三元运算符typeName检查,它应该显示两次。我圈出的地方应该是文本1内容而不是文本2内容的新块。否则我们就很接近我想要的结果了。当我在cms中测试时,只要它能处理它们以不同的顺序出现,而不仅仅是一排


如果在所有BlockGridWrapper组件之上,您对所有新块组件都满意,那么这应该是可行的。如果您不希望新块组件散布,那么应该包装连续的BlockGridWrapper组件组

您可以这样做:

let newBlockArr = [];
let blockgridArr = [];
data.datoCmsProject.projectBlock.forEach(v => {
  if (v.__typename === 'DatoCmsSingleProjectBlockContent') {
    newBlockArr.push( <NewBlock key={v.id}>Text Here</NewBlock> );
  } else {
    blockGridArr.push(
      <BlockGridWrapper>
        <BlockGrid key={v.id}>  
          <div>{projectEntry.titleOfGridSection}</div>
          <Img fluid={v.imageOfGridBlock.fluid} /> 
        </BlockGrid>
      </BlockGridWrapper>
    );
  }
});
或者这个:

let newBlockArr = data.datoCmsProject.projectBlock.filter(v => v.__typename === 'DatoCmsSingleProjectBlockContent').map(v => ( <NewBlock key={v.id}>Text Here</NewBlock> ));
let blockgridArr = data.datoCmsProject.projectBlock.filter(v => v.__typename !== 'DatoCmsSingleProjectBlockContent').map(v => (
  <BlockGridWrapper>
    <BlockGrid key={v.id}>  
      <div>{projectEntry.titleOfGridSection}</div>
      <Img fluid={v.imageOfGridBlock.fluid} /> 
    </BlockGrid>
  </BlockGridWrapper>
));
其次是:

return (
  <div>{newBlockArr}</div>
  <div>{blockgridArr}</div>
);

您正在执行if-else,因此您的BlockGridWrapper将无法在阵列中持续可用。您的映射数组可能看起来像

[
 <BlockGridWrapper ... ,
 <BlockGridWrapper ...,
 < NewBlock ...,
 <BlockGridWrapper...

]


好的,我想您可以创建一个连续元素数组,然后在它们上面运行循环。差不多


const wrap = data => {
  const res = [[data[0]]];
  let curr = data[0];
  // let curr = 0;
  let idx = 0;
  for (let i = 1; i < data.length; i++) {
    if (data[i].__typename === curr.__typename) {
      res[idx].push(data[i]);
    } else {
      curr = data[i];
      idx += 1;
      res[idx] = [curr];
    }
  }
};

const wrappedData = wrap(data.datoCmsProject.projectBlock);

/* wrappedData will look like (maintaining the order)

[ 
  [
  {__typename: 'DatoCmsSingleProjectBlockContent',...},
  {__typename: 'DatoCmsSingleProjectBlockContent',...},
  {__typename: 'DatoCmsSingleProjectBlockContent',...},
  ], 
  [
    {__typename: 'NotDatoCmsSingleProjectBlockContent'},
    {__typename: 'NotDatoCmsSingleProjectBlockContent'},
    {__typename: 'NotDatoCmsSingleProjectBlockContent'}
  ],
  [ 
    {__typename: 'DatoCmsSingleProjectBlockContent',...},
    {__typename: 'DatoCmsSingleProjectBlockContent',...},
  ],
  // and so on
]




*/


Now in your render you gotta do a nested loop:


wrappedData.map(list => {
  return (
    <div>
      {list.map(l =>
        l._typeName === "DatoCmsSingleProjectBlockContent" ? (
          <NewBLock />
        ) : (
          <BlockWrapper />
        )
      )}
    </div>
  );
});




现在,通过分离映射,它们不一定是按顺序出现的,它们都在graphQL中的一个查询中,所以我需要它们按照在cms中输入的顺序出现。我将在上面添加我的查询。对于您的解决方案,我认为它会让所有的新块排成一行,然后是所有的notnewblock,但是如果它在cms中的顺序是那样的,它应该是交替的,这取决于。我将在上面添加我的查询,如果它有助于您理解我的用例,您是说如果您的所有BlockGridWrapper元素都出现在一行中,那么它们会出现吗?比如NewBlock,NewBlock,NewBlock,BlockGridWrapper,BlockGridWrapper,NewBlock,NewBlock,BlockGridWrapper,BlockGridWrapper,等等?没错,这都是变量,因为它们都是从cmshmm输入的,也许我解释得不对。我希望它能够去blockGridWrapper,newBlock,newBlock,blockGridWrapper。。。无论在cms中输入的顺序是什么,它们都应该出现在页面中。但是blockGridWrapper的开头和结尾应该始终有一个wrapping和closing div,因此如果它看起来像这个blockGridWrapper,blockgridwrappernewblock,blockgridwrappernewblock,newblock,newblock,blockGridWrapper,blockGridWrapper,BlockGridWrapper我希望BlockGridWrapper组件在进入cms时出现,这样就可以[newblock,BlockGridWrapper,BlockGridWrapper,newblock]等等。这有意义吗?对于第一部分,我尝试将wrappedData记录到控制台中,但我没有定义,我将代码放在组件const IndexPage={data}=>{在返回之前,当我控制台记录wrap中的内容时,它包含了我所有的数据console.logdata.datoCmsProject.projectBlock;我添加了控制台日志的输出,以查看这是否有助于调试为什么当我使用wrap函数时,将其放入变量中,而控制台日志中的变量未定义。哦,我认为我需要在函数中返回resn现在我得到了数组中的数据。好的,我现在要尝试第二部分。好的,因为某种原因,它在应该输出的时候输出。我将在上面添加一个输出html的屏幕截图。

const newBlocks = data.datoCmsProject.projectBlock.filter(projectEntry => projectEntry.__typename === 'DatoCmsSingleProjectBlockContent')

const notNewBlocks = data.datoCmsProject.projectBlock.filter(projectEntry => projectEntry.__typename !== 'DatoCmsSingleProjectBlockContent')


return (
   <WhateverYourComponentIs>
       ...

      {newBlocks.map(projectEntry =><NewBlock key={projectEntry.id}></NewBlock> )}
      <div>{notNewBlocks.map(projectEntry => <BlockGridWrapper>...</BlockGridWrapper> )}</div>

   </<WhateverYourComponentIs

)

const wrap = data => {
  const res = [[data[0]]];
  let curr = data[0];
  // let curr = 0;
  let idx = 0;
  for (let i = 1; i < data.length; i++) {
    if (data[i].__typename === curr.__typename) {
      res[idx].push(data[i]);
    } else {
      curr = data[i];
      idx += 1;
      res[idx] = [curr];
    }
  }
};

const wrappedData = wrap(data.datoCmsProject.projectBlock);

/* wrappedData will look like (maintaining the order)

[ 
  [
  {__typename: 'DatoCmsSingleProjectBlockContent',...},
  {__typename: 'DatoCmsSingleProjectBlockContent',...},
  {__typename: 'DatoCmsSingleProjectBlockContent',...},
  ], 
  [
    {__typename: 'NotDatoCmsSingleProjectBlockContent'},
    {__typename: 'NotDatoCmsSingleProjectBlockContent'},
    {__typename: 'NotDatoCmsSingleProjectBlockContent'}
  ],
  [ 
    {__typename: 'DatoCmsSingleProjectBlockContent',...},
    {__typename: 'DatoCmsSingleProjectBlockContent',...},
  ],
  // and so on
]




*/


Now in your render you gotta do a nested loop:


wrappedData.map(list => {
  return (
    <div>
      {list.map(l =>
        l._typeName === "DatoCmsSingleProjectBlockContent" ? (
          <NewBLock />
        ) : (
          <BlockWrapper />
        )
      )}
    </div>
  );
});