Using reduce in JavaScript to form a fresh object

I've been struggling with creating an object using reduce from a nested array. The task is to generate a new object with keys named _uid and values matching the initialValue from the objects that contain both properties. I have written a function that can iterate through the nested arrays but I am facing difficulty in returning the new object with all the extracted properties. I attempted to use shallow and deep copy methods to clone the accumulator, but without success. Is there anyone who could assist me?

This is the structure of the nested array:

export const formData = [
  {
component: 'page',
label: 'Page 1',
_uid: '0c946643-5a83-4545-baea-055b27b51e8a',
fields: [
  {
    component: 'field_group',
    label: 'Name',
    _uid: 'eb169f76-4cd9-4513-b673-87c5c7d27e02',
    fields: [
      {
        component: 'text',
        label: 'First Name',
        initialValue: '2345432',
        type: 'text',
        _uid: '5b9b79d2-32f2-42a1-b89f-203dfc0b6b98',
      },
      {
        component: 'text',
        label: 'Last Name',
        initialValue: '2345432',
        type: 'text',
        _uid: '6eff3638-80a7-4427-b07b-4c1be1c6b186',
      },
    ],
  },
  ...
],
  },
  ...
]

The logic behind the function:

 function getInitialValues(formData = []) {
    return Array.from(formData).reduce((acc, currentValue, idx) => {
      const arrayOfStrings = ['page', 'field_group', 'options']
      const str = currentValue.component
      const found = arrayOfStrings.find((v) => str === v)
      if (found) {
        // console.log('entered', currentValue)
        getInitialValues(currentValue?.fields)

        return acc
      }

      if (
        (currentValue.component === 'text' || currentValue.component === 'select') &&
        currentValue.label === 'Conditional Field'
      ) {
        acc[currentValue._uid] = currentValue?.initialValue

        return acc
      }
      return acc
    }, {})
  }

The expected outcome should resemble this for all unique _uids that have initialValues assigned:

{
5b9b79d2-32f2-42a1-b89f-203dfc0b6b98: '2345432',
5b9b79d2-32f2-42a1-b89f-203dfc0b6b97: '2345431',
5b9b79d2-32f2-42a1-b89f-203dfc0b6b96: '2345430',

}

Answer №1

In my experience, I've discovered that separating the extraction of _uid/initialValue properties from their formatting into an output object makes the process much simpler.

Below are a recursive extract function and a straightforward convert function based on it.

const extract = (xs) =>
  xs .flatMap (({initialValue, _uid, fields = []}) =>
    [[_uid, initialValue], ...extract (fields)]
  ) .filter (([_, init]) => init != null)

const convert = xs =>
  Object .fromEntries (extract (xs))

const formData = [{component: "page", label: "Page 1", _uid: "0c946643-5a83-4545-baea-055b27b51e8a", fields: [{component: "field_group", label: "Name", _uid: "eb169f76-4cd9-4513-b673-87c5c7d27e02", fields: [{component: "text", label: "First Name", initialValue: "2345432", type: "text", _uid: "5b9b79d2-32f2-42a1-b89f-203dfc0b6b98"}, {component: "text", label: "Last Name", initialValue: "2345432", type: "text", _uid: "6eff3638-80a7-4427-b07b-4c1be1c6b186"}]}, {component: "text", label: "Email...

console .log (convert (formData))

.as-console-wrapper {max-height: 100% !important; top: 0}

The question also indicates a need for data updating. In my opinion, this should be treated as a separate phase, which appears to be within your capabilities already.

Answer №2

The issue lies within:

 if (found) {
    // console.log('entro', currentValue)
    getInitialValues(currentValue?.fields)

    return acc
  }

In this scenario, the invocation of getInitialValues is expected to yield a result that is not stored in acc.

To rectify this, one potential solution is as follows:

    if (found) {
        const res = getInitialValues(currentValue.fields);
        return Object.assign(acc, res);
    }

While there could be other unresolved matters, this particular discrepancy caught my attention.

Please note: two-thirds of the identifiers mentioned in the "expected outcomes" section are absent from the initial code snippet (the illustration of formData). Regarding the remaining one with uid:

5b9b79d2-32f2-42a1-b89f-203dfc0b6b98
, its label is 'First Name' instead of 'Conditional Field,' explaining why it doesn't feature in the output.

(Enhanced) Revised code block

function getInitialValues (formData = []) {
    return formData.reduce((acc, currentValue) => {
        const arrayOfStrings = ['page', 'field_group', 'options'];
        const str = currentValue.component;
        const found = arrayOfStrings.find((v) => str === v);
        if (found) {
            const res = getInitialValues(currentValue.fields);
            return Object.assign(acc, res);
        }

        if (
            (currentValue.component === 'text' || currentValue.component === 'select') &&
            currentValue.label === 'Conditional Field'
        ) {
            if (currentValue.initialValue) {
                acc[currentValue._uid] = currentValue.initialValue;
            }
        }
        return acc;
    }, {});

Answer №3

Using a simple forEach loop with recursion proved to be the most straightforward approach for me.

const formData = [{
    component: 'page',
    label: 'Page 1',
    _uid: '0c946643-5a83-4545-baea-055b27b51e8a',
    fields: [{
        component: 'field_group',
        label: 'Name',
        _uid: 'eb169f76-4cd9-4513-b673-87c5c7d27e02',
        fields: [{
            component: 'text',
            label: 'First Name',
            initialValue: '2345432',
            type: 'text',
            _uid: '5b9b79d2-32f2-42a1-b89f-203dfc0b6b98',
          },
          {
            component: 'text',
            label: 'Last Name',
            initialValue: '2345432',
            type: 'text',
            _uid: '6eff3638-80a7-4427-b07b-4c1be1c6b186',
          },
        ],
      },
      {
        component: 'text',
        label: 'Email',
        initialValue: '2345432',
        type: 'email',
        _uid: '7f885969-f8ba-40b9-bf5d-0d57bc9c6a8d',
      },
      {
        component: 'text',
        label: 'Phone',
        initialValue: '2345432',
        type: 'text',
        _uid: 'f61233e8-565e-43d0-9c14-7d7f220c6020',
      },
    ],
  },
  // Additional data goes here...
]

// Function that retrieves initial values from form data using recursion
function getInitialValues(formData = [], output=[]) {
  // Implementation of the function goes here...
}

console.log(getInitialValues(formData))

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Fetching the "User ID" variable from localStorage to PHP with angularjs - a quick guide

My goal is to retrieve "Notes" based on the "userID" value. Here is my approach: I used angular.js to trigger the PHP function $scope.getData = function(){ $http.get( '../php/displayNotes.php' ).success(function(data){ $ ...

Is the contact form confirmation message displaying too prominently?

I am currently troubleshooting two different forms on a website I'm developing, and I am unsure of the exact cause of the issue. Form 1: Form 2: When attempting to submit Form 1 without entering any information, an error message is displayed exactl ...

The styles for Material-UI Popover are not taking effect

I have integrated the Popover component from Material-UI into my application: <Popover anchorEl={AnchorElement} anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} open={props.isVisible} className='popove ...

Firefox is mistakenly interpreting a pasted image from the clipboard as a string instead of a file, causing

I am facing an issue where I am attempting to extract images from a contenteditable div using the paste event. The code works perfectly in Chrome but does not function as expected in Firefox. I have implemented the following code: $(window).on("paste& ...

Transferring an object from the factory to the controller

I'm currently working on setting up a factory that sends an ajax request to an API and then returns a data object. Here is the code snippet I have written: app.factory('Test', function($http, $q) { var data = {response:{}}; var getM ...

What is the rationale behind allowing any type in TypeScript, even though it can make it more challenging to detect errors during compile time?

Why is it that all types are allowed in TypeScript? This can lead to potential bugs at runtime, as the use of type "any" makes it harder to detect errors during compilation. Example: const someValue: string = "Some string"; someValue.toExponentia ...

The addition of a cancel swipe feature to an HTML5 eBook is causing the text input field for note-taking to malfunction

I am currently working on the development of a process to create HTML5 based eBooks for both desktop and mobile use using Adobe InDesign and exporting them with a plugin called In5. This plugin allows for the incorporation of html, css, and javascript duri ...

Switch from buffer to base64 encoding for viewing in Angular

Hello, I have developed an application using the MEAN stack. Currently, I am facing an issue with retrieving images from my endpoint. The image array values that I am receiving look like this: 8,8,7,7,9,8,9,8,9,8,9,9,8,8,8,8,7,9,7,7,9,10,16,13,8,8,16,9,7, ...

Executing a closure within a promise's callback

Currently, I am working on implementing a queue system for a web application in order to locally store failed HTTP requests for later re-execution. After reading Mozilla's documentation on closures in loops, I decided to create inner closures. When ...

How to streamline a JSON array within ADF copy activity

Is there a way to flatten an array of complex JSONs with nested arrays in the copy activity? Despite checking forums and samples, I've tried several methods without success due to the complexity of my JSON structure. Here's the JSON data: { & ...

Utilizing on() in conjunction with a map function

Currently, I am in the process of refactoring my code and have decided to revisit how I handle on events by utilizing mapping. Below is a snippet of what I currently have: $('img#sorc').on({ mousemove: function (e) { alert('tes ...

Determining the appropriate array key to use in a Twig template

Within the Symfony2 Controller class, I am passing an array called $things to the render method like this: return $this->render('Bundle:Default:action.html.twig', $things); The associative array $things has the following values: Array ( [id ...

Utilize JavaScript or jQuery to segment HTML elements

Looking for a front-end solution to a common practice. In the past, I've stored reusable HTML elements (such as <nav>, <header>, <footer>, etc.) in a functions.php file and used PHP functions to include them on multiple pages. This ...

Handling Errors with Async-Await in JavaScript: Struggling to Retrieve Error Specifics from Error Objects

Within my Node Express JS web application, there is a specific function chain present where an API function attempts to call a service function and handle any errors that may be thrown from within the service function. Located in FWBDataExtracService.js c ...

Place the simulation nodes in designated locations

Is there a proper way to position nodes at specific coordinates using simulation force in D3.js? I am trying to place nodes at specific positions with forceX/Y simulation in D3.js. My understanding is that setting the strength to 0 should result in no for ...

Discovering identical elements within a list in Python through index-based location scanning

Check out this JavaScript code that can determine whether there are any duplicate elements in an array. function findDuplicates(arr) { let seen = []; for (let i = 0; i < arr.length; i++) { if(seen[arr[i]] === 1) { ...

Select element click event not functioning on Mac computers

My <select> element is not responding to the click event in MacOS Chrome when using Javascript. This issue has been discussed on platforms like Stack Overflow. Check out this example <select id='hodor'> <option>Jon Snow< ...

I'm having trouble getting $.getJSON to function properly

Has anyone encountered issues with the getJSON function in jQuery? function loadJSON(){ console.log("loading JSON") var jsonFile = themeURL+"/map.json" $.getJSON(jsonFile, function(data){ console.log("loaded JSON") $("#infobox").fadeOut(1000 ...

I'm encountering an issue where the this.props object is undefined even though I've passed actions to mapDispatchToProps. What could

Summary: The issue I'm facing is that in the LoginForm component, this.props is showing as undefined even though I have passed actions in mapDispatchToProps. I've debugged by setting breakpoints in the connect function and confirmed that the act ...

Sending information into MySQL using NodeJS with the help of Postman

As a newcomer in the field, I am exploring how to combine MySQL with nodeJS for integrating projects into WordPress. app.post('/users/add', (req, res) => { id = req.body.id, firstname = req.body.firstname, surname = req.body.surname ...