dangre00
dangre00

Reputation: 450

useState can't seem to properly map array

I have a simple page, which in fdoes quite a bit more, but I've condensed it down to the problem code. I'm pulling data from Cloud Firestore. I have one collection of data that represents the sequence of the objects. The other collection are the objects themselves:

import React, { useState } from "react";

const App = () => {
  const boardSequence = ["boardid2", "boardid1"];
  const boardData = [
    {
      boardid1: {
        boardValue: "Sales",
        boardColor: "#003c8a",
        boardDifference: "#FFFFFF"
      }
    },
    {
      boardid2: {
        boardValue: "Follow Ups",
        boardColor: "#000000",
        boardDifference: "#FFFFFF"
      }
    }
  ];

  const [boards] = useState(boardData);
  const [sequence] = useState(boardSequence);
  return (
    <div>
      {sequence.map((boardId, index) => {
        return <p key={index}>{boards[boardId].boardValue}</p>;
      })}
    </div>
  );
};
export default App;

I start by mapping through the sequence array, then try to display values from the board array, but getting error

Cannot read property 'boardValue' of undefined

EDIT: Here is the code I'm using to get the data. It looks like the real question is, how do I break this out of the array and into an object that can be readable?

    const promise1 = appBase.firestore().collection("workflow").get();
    const promise2 = appBase.firestore().collection("boards").get();

    Promise.all([promise1, promise2])
      .then((snapshot) => {
        // console.log(snapshot[0].docs.data().boardIds);
        const newBoardIds = snapshot[0].docs.map((doc) => {
          return doc.data().boardIds;
        });
        setBoardIds(newBoardIds[0]);

        const newBoards = snapshot[1].docs.map((doc) => {
          return {
            [doc.id]: {
              boardValue: doc.data().boardValue,
              boardColor: doc.data().boardColor,
              boardDifference: doc.data().boardDifference,
            },
          };
        });

        console.log(newBoards);
        setBoards(newBoards);
        // setSettings({ ...settings, dataLoaded: true });
        setDataLoaded(true);
      })
      .catch((error) => {
        console.log("error returned on boards: " + error);
      });

Upvotes: 0

Views: 1054

Answers (3)

Emeka Augustine
Emeka Augustine

Reputation: 931

You are looping through a sequence array of strings; I think you wanted to loop through boards; which is an array of objects. Like so:

import React, { useState } from "react";

const App = () => {
  const boardSequence = ["boardid2", "boardid1"];
  const boardData = [
    {
      boardid1: {
        boardValue: "Sales",
        boardColor: "#003c8a",
        boardDifference: "#FFFFFF"
      }
    },
    {
      boardid2: {
        boardValue: "Follow Ups",
        boardColor: "#000000",
        boardDifference: "#FFFFFF"
      }
    }
  ];

  const [boards] = useState(boardData);
  const [sequence] = useState(boardSequence);
  return (
    <div>
      {boards.map((boardId, index) => {
        return <p key={index}>{boards[boardId].boardValue}</p>;
      })}
    </div>
  );
};
export default App;

Upvotes: 1

hgb123
hgb123

Reputation: 14881

You should transform boardData from array to object. In the demo I use reduce to achieve that

const [boards] = useState(
  boardData.reduce((acc, obj) => ({ ...acc, ...obj }), {})
);

Codesandbox demo

Edit awesome-chandrasekhar-cngnx

Upvotes: 1

Kenny John Jacob
Kenny John Jacob

Reputation: 1198

Here,

{sequence.map((boardId, index) => {
  return <p key={index}>{boards[boardId].boardValue}</p>;
})}

boards is an array, and hence looks for integer index. If you wanted to look up by the key, then your data should be of this format,

const boardData = {
    boardid1: {
      boardValue: "Sales",
      boardColor: "#003c8a",
      boardDifference: "#FFFFFF",
    },
    boardid2: {
      boardValue: "Follow Ups",
      boardColor: "#000000",
      boardDifference: "#FFFFFF",
    },
};

Upvotes: 1

Related Questions