Как преобразовать данные? [Как отрендерить данные из массива в React - некоторые последовательно, а некоторые объединенными в группу]

Ребята, подскажите, пожалуйста, как преобразовать данные.
Исходные данные:

const widgets = [
    {
        type: "Title",
        data: {
            title: "title1",
            subTitle: "subTitle1"
        }
    },
    {
        type: "Title",
        data: {
            title: "title2",
            subTitle: "subTitle2"
        }
    },
    {
        type: "Title",
        data: {
            title: "title3",
            subTitle: "subTitle3"
        }
    },
    {
        type: "TitleTwo",
        data: {
            title: "TitleTwo title",
            subTitle: "TitleTwo subTitle"
        }
    },
    {
        type: "TitleTwo",
        data: {
            title: "TitleTwo title",
            subTitle: "TitleTwo subTitle"
        }
    },
    {
        type: "New",
        data: {
            title: "new title1",
            subTitle: "new subTitle1"
        }
    },
    {
        type: "New",
        data: {
            title: "new title2",
            subTitle: "new subTitle2"
        }
    },
    {
        type: "NewTitle",
        data: {
            title: "NewTitle title1",
            subTitle: "NewTitle subTitle1"
        }
    },
    {
        type: "NewTitleTwo",
        data: {
            title: "NewTitleTwo title",
            subTitle: "NewTitleTwo subTitle"
        }
    }
]

Данные которые необходимо получить (объединение одинаковых типов в массив):
В моем примере, я говорю, для типов Title и New, преобразование необходимо с сохранением своего расположения, как в исходном массиве, а остальные типы остаются с такой же структурой и в том же месте.
Новое состояние:

const widgetsTransform = [
    {
        type: "SectionTitle",
        children: [
            {
                type: "Title",
                data: {
                    title: "title1",
                    subTitle: "subTitle1"
                }
            },
            {
                type: "Title",
                data: {
                    title: "title2",
                    subTitle: "subTitle2"
                }
            },
            {
                type: "Title",
                data: {
                    title: "title3",
                    subTitle: "subTitle3"
                }
            }
        ]
    },
    {
        type: "TitleTwo",
        data: {
            title: "TitleTwo title",
            subTitle: "TitleTwo subTitle"
        }
    },
    {
        type: "TitleTwo",
        data: {
            title: "TitleTwo title",
            subTitle: "TitleTwo subTitle"
        }
    },
    {
        type: "SectionNew",
        children: [
            {
                type: "New",
                data: {
                    title: "new title1",
                    subTitle: "new subTitle1"
                }
            },
            {
                type: "New",
                data: {
                    title: "new title2",
                    subTitle: "new subTitle2"
                }
            }
        ]
    },
    {
        type: "NewTitle",
        data: {
            title: "NewTitle title1",
            subTitle: "NewTitle subTitle1"
        }
    },
    {
        type: "NewTitleTwo",
        data: {
            title: "NewTitleTwo title",
            subTitle: "NewTitleTwo subTitle"
        }
    }
]

Если это преобразование связано с задачей Как сделать динамический рендеринг? [Как отредерить данные из массива в секции согласно типам], то тут начинаются нюансы. То преобразование которое ты хочешь сделать сделает сложным будущую работу с данными. Из-за их неоднородности (член widgetsTransform будет разной формы (какие-то с массивом, какие-то без).

Поправь если я неправ - твоя задача такая что некоторые виджеты нужно объединить в группы при рендере, а некоторые - нет. Я бы смотрел на список виджетов и группирование как два независимых аспекта, и выражал бы их двумя структурами данных. И через комбинацию этих структур решал бы как отрисовывать:

const widgets = {
    Title: [{type: "Title", data: {}}]
    TitleTwo: [{type: 'TitleTwo', data: {}}, {}]
}
const sections = {
    Title: {title: 'Section title'},
    New: {title: 'SectionNew'}
}

И тогда у тебя на этапе рендера есть свобода выбрать как рендерить виджеты без необходимости отражать их физическое положение в структуре данных:

// sections is defined
function Components(componentsData) {
	const map = getMapByName(componentsData)
	return <React.Fragment>
		Object.keys(map).map((componentType) => {
			const components = map[componentType]
			const sectionTitle = sections[componentType]
			return <section key={componentType}>
				{sectionTitle ? <h1>{sectionTitle}</h1> : null}
				components.map((componentData, index) => {
					return <Factory component={componentData} key={index} />
				})
			</section>
		})
	</React.Fragment>
}

Идея, похожая, как ты описал. Т.е. есть линейный список виджетов. В цикле я их перебираю и в зависимости от типа отрисовываю какой компонент. Т.е. backend рулит порядком отображения. Но, выходит, что некотрые типы виджетов мне нужно поместить в div.

Например

section - первый виджет

section - второй виджет

div

    section - третий виджет (у этого виджета type Title)

    section - четвертый виджет (у этого виджета type Title)

section - пятый виджет

В текущей фибрике:


section - первый виджет

section - второй виджет

section - третий виджет (у этого виджета type Title)

section - четвертый виджет (у этого виджета type Title)

section - пятый виджет

Спасибо за твой совет. Но всё же попрошу, если тебе не сложно, ты мог бы в codepen накидать дэмку?

Работающую демку - нет. Это много времени и усилий, которые я не могу просто так выделить. А вот примерный код - пожалуйста показать.

Понял задачу. Все равно я бы оставлял данные как можно чище, не пытался бы отразить в них то как они рендерятся. Алгоритм в стиле “рендерим копоненты из массива, встречаем компонент тип которого нужно сложить в секцию - рендерим всю секцию компонент”. Маппинг того какой тип компонент должен идти в секцию закодирован в sections. componentsData - оригинальный массив с объектами компонент.

const sections = {
    'New': { title: 'This is section for widget type of New' },
    'Title': { title: 'This is for "Title" widget type' }
}

function getMapByName(componentsArr) {
    return componentsArr.reduce((res, componentData) => {
        const type = componentData.type
        if (!res[type]) {
            res[type] = []
        }
        res[type].push(componentData)
    }, {})
}

function Components(componentsData) {
    const map = getMapByName(componentsData)
    const renderedSections = {}
    return <React.Fragment>
        {componentsData.map((componentType, index) => {
            const sectionTitle = sections[componentType]
            if (sectionTitle) {
                if (renderedSections[componentType]) { // уже отрендерили секцию для компонентов этого типа
                    return null
                } else { // тут рендарим все компоненты этого типа
                    const componentsToRender = map[componentType]
                    renderedSections[componentType] = true
                    return <div key={index}>
                        {componentsToRender.map((component, index) => {
                            <Factory component={component} key={index}/>
                        })}
                    </div>
                }
            } else {
                return <section key={index}>
                    return <Factory component={componentData} key={index}/>
                </section>
            }
        })}
    </React.Fragment>
}

Идея понятна. Спасибо тебе.