Search code examples
javascriptreactjsreact-nativevictory-charts

React Native how to create a VictoryPie from nested data


In my React Native application, I am accessing data from my store in the following form:

Array [
  Checkout {
    "date": 2020-12-27T13:24:08.734Z,
    "id": "Sun Dec 27 2020 08:24:08 GMT-0500 (EST)",
    "items": Array [
      Object {
        "productBrand": "Microsoft",
        "productCategory": "Gaming",
        "productId": "p1",
        "productTitle": "Xbox",
        "quantity": 2,
        "x": 1.815,
      },
      Object {
        "productBrand": "Apple",
        "productCategory": "Computers",
        "productId": "p2",
        "productTitle": "MacBook Pro",
        "quantity": 1,
        "x": 1.905,
      },
    ],
    "total": 3.720,
  },
  Checkout {
    "date": 2020-12-27T13:24:47.790Z,
    "id": "Sun Dec 27 2020 08:24:47 GMT-0500 (EST)",
    "items": Array [
      Object {
        "productBrand": "Apple",
        "productCategory": "Computers",
        "productId": "p2",
        "productTitle": "MacBook Pro",
        "quantity": 1,
        "x": 1.905,
      },
    ],
    "total": 1.905,
  },
]

I am trying to use VictoryPie to create a pie chart that shows productBrand weighted by the sum of x over all the objects. In this example, I would need a pie chart showing Microsoft and Apple, weighted by 1.815 and 2*1.905 = 3.81, respectively. Is there any way to do this without writing a separate function to calculate these sums? I would like the pie chart to update automatically every time new data is added to the store.

I tried this, where history is a variable containing the above array but no pie chart is produced.

<VictoryPie data={history} x={(data) => data.items.productBrand} y={(data) => data.items.x} />

Solution

  • For anyone trying to do something similar, I ended up extracting the data I needed by using a nested for loop within the useSelector hook:

    const allBrands = useSelector(state => {
        let allData = {};
        for (const key1 in state.history.history) {
          for (const key2 in state.history.history[key1].items) {
            if (allData.hasOwnProperty(state.history.history[key1].items[key2].productBrand)) {
              allData[state.history.history[key1].items[key2].productBrand] += state.history.history[key1].items[key2].x;
            } else {
              allData[state.history.history[key1].items[key2].productBrand] = state.history.history[key1].items[key2].x;
            }
          }
        };
        let dataArray = [];
        for (const prop in allData) {
          dataArray.push({ brand: prop, total: allData[prop] })
        }
        return dataArray
      });
    

    Passing allBrands to the VictoryPie data prop produced the correct pie chart.