anongal
anongal

Reputation: 45

How can I groupby in React/Redux code (new to frontend)?

I am having difficulty with this function to run in my React/Redux code. I am fairly new to React (mostly work on backend) so I am not sure why it's not running as expected. Is it in the right place? I am also having trouble finding where console.log is printing in the console, since the console is set up with prev action, action, next state patterns....

I have this function defined in my 'actions.js' (where it is also called later on):

const groupBy = (array, key) => {
    return array.reduce((result, currentValue) => {(
     result[currentValue[key]] = result[currentValue[key]] || []).push(
        currentValue
      );
      return result;
    }, {}); 
  };

Here is where the function is called (same file):

export function getAlerts() {
    return dispatch => {
        api.get('notifications', (response) => {
            const grouped = groupBy(response.results.data, 'email');
            dispatch(updateFetchedAlerts(grouped));
        }, (error) => {
            console.warn(error);
        })
    }
}

The input, response.results.data, looks something like this:

[{"email": [email protected], "is_active": true, "alert_id": 1, "pk": 1}, 
{"email": [email protected], "is_active": true, "alert_id": 2, "pk": 2}, 
{"email": [email protected], "is_active": true, "alert_id": 1, "pk": 3}]

I want it to look like this:

[{"[email protected]": [{"is_active": true, "alert_id": 1, "pk": 1}, 
                    {"is_active": true, "alert_id": 2, "pk": 2}],
"[email protected]": [{"is_active": true, "alert_id": 1, "pk": 3}]}]

but it seems to not be running this function, I've rerun yarn build and used incognito...

UPDATE: This function actually WORKS! Thanks all. The redux developer tools are very helpful. Now the second problem is I need to add in my own keys.... So ideally the result would look like this. Preferably no lodash!:

[{"email": "[email protected]",
"alerts": [{"is_active": true, "alert_id": 1, "pk": 1}, 
           {"is_active": true, "alert_id": 2, "pk": 2}]},
{"email": "[email protected]",
"alerts": [{"is_active": true, "alert_id": 1, "pk": 3}]}]

Upvotes: 2

Views: 822

Answers (2)

Drew Reese
Drew Reese

Reputation: 202979

You can take the same function you used to group by which yields object of shape

{ [string]: object[] }

Using Object.entries allows you to convert this to an array of key-value pairs that you can map to an array of objects with shape

{
  email: string,
  alerts: object[],
}

Function updates

const groupBy = (array, key) =>
  array.reduce((result, { [key]: k, ...rest }) => {
    (result[k] = result[k] || []).push(rest);
    return result;
  }, {});

const groupDataBy = (array, key) =>
  Object.entries(groupBy(array, key)).map(([email, alerts]) => ({
    email,
    alerts
  }));

The map function callback ([email, alerts]) => ({ email, alerts }) uses array destructuring to assign the array of [key, value] to named variables email and alerts, and object shorthand notation to create an object with keys named for the variables.

const data = [{
    "email": "[email protected]",
    "is_active": true,
    "alert_id": 1,
    "pk": 1
  },
  {
    "email": "[email protected]",
    "is_active": true,
    "alert_id": 2,
    "pk": 2
  },
  {
    "email": "[email protected]",
    "is_active": true,
    "alert_id": 1,
    "pk": 3
  }
];

const groupBy = (array, key) =>
  array.reduce((result, { [key]: k, ...rest }) => {
    (result[k] = result[k] || []).push(rest);
    return result;
  }, {});

const groupDataBy = (array, key) =>
  Object.entries(groupBy(array, key)).map(([email, alerts]) => ({
    email,
    alerts
  }));

const res = groupDataBy(data, 'email');

console.log(res)

Upvotes: 1

Ok, first the console is in the Browser Developer Tools seccion console. There you can view all the console.log. In Chrome you can open it by pressing F12.

And the other question, the function that you`re needing is:

//Function groupBy.
function groupBy(array, key) {
  let arrayReduced = array.reduce(
    (result, { [key]: k, ...rest }) => {
      (result[k] = result[k] || []).push(rest);
      return result;
    },
    {}
  );
  return arrayReduced;
}

//Your example data.
const group = [
  {
    email: '[email protected]',
    is_active: true,
    alert_id: 1,
    pk: 1,
  },
  {
    email: '[email protected]',
    is_active: true,
    alert_id: 2,
    pk: 2,
  },
  {
    email: '[email protected]',
    is_active: true,
    alert_id: 1,
    pk: 3,
  },
];

//Function  executed
const result = groupBy(group, 'email');

//Result
console.log(result);

I hope it helps!

Upvotes: 1

Related Questions