How can I extract a nested array of objects and put them in the core array?

I am working on a functionality where I need to group some items and also ungroup them.

Some days ago I asked this question: How can I group specific items within an object in the same array and delete them from the core array? where a couple of people helped me solving the grouping part. But it is very related to this question.

What I need to do now, is to ungroup the items with the exact same requirement: ungroup the checked === true group and put the items back from where they came from and remove all duplicates.

Here is a reproducible demo with both functionalities: https://codesandbox.io/s/ts-react-grouping-forked-rmwhr?file=/src/App.tsx

And here the relevante piece of code:

const handleUngroupingQuestions = (): void => {
    const questionAddedCopy: VariableConfig[] = [...questionAdded]
    const filteredByChecked: VariableConfig[] = questionAddedCopy.filter((q: VariableConfig) => isCheck.includes(q.id))

    if (isCheck.length) {
      setCheck([])

      const extractGroup = (i: number): VariableConfig[] => filteredByChecked[i].questionGroup
      const addChecked = (q: VariableConfig): VariableConfig => ({ ...q, questionGroup: [] })

      // @TODO
      // Remove this when we have a proper data structure
      clearVariable()

      const nestChecked = (qs: VariableConfig[], found = false) =>
        qs.flatMap((q: VariableConfig, i: number) => {
          if (filteredByChecked.includes(q)) {
            if (found) {
              return []
            } else {
              found = true
              return [...[addChecked(q)], ...extractGroup(i)]
            }
          } else {
            return [q]
          }
        })

      const getNew = [...nestChecked(questionAdded)]

      console.log({ getNew: JSON.stringify(getNew, null, 2) })

      addQuestion(getNew.filter((g, i, a) => a.indexOf(g) === i))
    }
  }

For some reason right now I am getting an error:

Cannot read property 'questionGroup' of undefined

Something is happening with an index.

So what I need is to group all of the items with the checked property being true. Then click on ungroup and bring the items back to its original position and deleting the current group. I must be able to do that even when there are multiple groups of questions.

What am I missing?

1 answer

  • answered 2021-03-03 03:27 OBN

    You start with an array length 5, then group to create an array length 3 (with the nested array inside the 2nd element of this)

    Then in your handleUngroupingQuestions function, the first variable filteredByChecked is defined via the filter function as an array with 1 element only (the single element with the nested array questionGroup)

    const filteredByChecked: VariableConfig[] = questionAdded.filter(
          (q: VariableConfig) => q.checked === true
        );
    

    Then when you try to ungroup, you are passing the length 3 array to the function, which takes a different index (the second element, index 1):

    const extractGroup = (i: number) => {
          console.log(i);
          return filteredByChecked.length ? filteredByChecked[i].questionGroup : [];
        };
    

    The i being passed to extractGroup here is 1, which does not exist as filteredByChecked is a length 1 array.

    Please consider this single map function as your ungrouping handler:

    const handleUngroupingQuestions = (): void => {
        const extractGroups = (groupedArr: Array) => {
          return groupedArr.flatMap((x) =>
            x.questionGroup.length > 0 ? [...x.questionGroup] : x
          );
        };
    
        const newQs = extractGroups(questionAdded);
        const sortedQs = newQs.sort((a, b) =>
          parseInt(a.name.slice(-1), 10) > parseInt(b.name.slice(-1), 10) ? 1 : -1
        );
    
        console.log(sortedQs);
        addQuestion(sortedQs);
      };
    

    Edit TS-React Grouping (forked)