Home > database >  How can I display different array values in react without getting map undefined?
How can I display different array values in react without getting map undefined?

Time:10-13

This is the original data:

const myArray = [
  'id': 'stuff', 'location': 'stuff2', 
  'phone_numbers'['stuff3','stuff4'], "address" : 'stuff5'
]


// so far, I'm getting the correct values back in an array from an API.
console.log(myReturnedArray) = [
{
"id": "10001",
"brand": "Best Brand",
"center_name": "Best Brand Texas",
"status": "Active",
"emails": [
  {
    "CreateDate": "October 12, 2022 at 10:59:09 AM UTC-5",
    "emailAddress": "[email protected]",
    "firstName": "Test",
    "lastName": "Tester",
    "id": "0eac8839-6e61-42f5-b55f-e2fa17b0262b",
    "licenseType": "Unlimited",
    "updateDate": "October 12, 2022 at 10:59:09 AM UTC-5",
    "userType": "STORE"
  }
],
"licenses": [
  {
    "CreateDate": "October 12, 2022 at 10:59:09 AM UTC-5",
    "licenseType": "STORE",
    "status": "ASSIGNED",
    "updatedBy": "SYSTEM",
    "updateDate": "October 12, 2022 at 10:59:09 AM UTC-5",
    "renewDate": "October 12, 2022 at 10:59:09 AM UTC-5",
    "expirationDate": "October 12, 2022 at 10:59:09 AM UTC-5",
    "id": "0eac8839-6e61-42f5-b55f-e2fa17b0262b"
   }
  ]
 }
]

*** whenever i try a map function i get the error "Objects are not valid as a React child (found: object with keys {id, brand, center_name, status, emails, licenses}). If you meant to render a collection of children, use an array instead." ***

I would like to display each value from my returned array in a div or span, but I keep getting errors like cannot get properties of undefined reading map, or a unique keys error whenever I try something.

// I would like to have each value from the object inside of myReturnedArray to use in my return statement.
return (
    <span>your email is : "[email protected]", </span>
    <div> your first name is : "Test" </div>
    <span> your last name is : "lastName": "Tester", </span>
);

Anytime I try and use a map function like this in my return statement:

{ myReturnedArray.map(item => <div>{item.name}</div>) } 

It returns myReturnedArray is undefined. But when I do:

{ JSON.stringify(myReturnedArray) }

It renders returnedArray as a string correctly. So I know the return method has access to the array; I just can't display it.

CodePudding user response:

Final solution: codeSandbox

Explantion to the errors you got:

1: The data structure you updated is very complex and nested with object inside array and arrays inside this object and so on. So, of course it will throw an error "Objects are not valid as a React child".

You can't put an entire object between div tags, You need to map this object fields one by one to have single values between each div.

2: About the "unique key" issue - this is a warning, not an error. It's always showing this warning when you map object items to elements without adding the key attribute to each item.

So in order to get rid of this warning, Just add the key attribute to the divs that are returned inside a map function, and choose some uniqe key.


How can you map it like this?

As I understood, The structure you have is one big array - myReturnedArray, and in this array you will have many(now you have just one) objects when each one contains:

  • An emails array which contains object(s).
  • An licenes array which contains object(s).
  • Some other key:value pairs.

In order to map myReturnedArray correctly - You'll need a ForEach loop that will map every big object inside of it, and then return all the mapped objects together.


First, I created an helper function that maps an array of objects(without nested arrays or something) to HTML div tags.

And I will use this function in order to map the emails and licenes arrays.

Helper function:

  const mapArrayOfObjects = (array) => {
    const arrayAsDivs = array.map((obj, index) => {
      const mappedObj = Object.entries(obj).map(([key, value]) => {
        return <div key={key}>{key   ' : '   value}</div>;
      });
      return (
        //Returns a div with one object of the array and space after it.
        <div key={'nestedObj'   index}>
          {mappedObj}
          <br />
        </div>
      );
    });
    return arrayAsDivs; //The function returns ALL the mapped objects in the array.
  };

It looks complex, but all it does is going through the array, and mapping each object to a big div tag with all the key:value pairs as nested divs. (And I added the br to have some space between the objects. (In your case you have just one object in the emails, but I assume that there would more.)

Using forEach

In this function, I map all the big objects that are inside myReturnedArray:

const allObjectsHTML = [];

  myReturnedArray.forEach((obj) => {
    const emailsAsDivs = mapArrayOfObjects(obj.emails);
    const licensesAsDivs = mapArrayOfObjects(obj.licenses);
    const otherFields = Object.entries(obj).map(([key, value]) => {
      if (!Array.isArray(value)) {
        return <div key={key}>{key   " : "   value}</div>;
      }
    });
    const objectAsHTML = (
      <div>
        <div>{otherFields}</div>
        <div>
          <h3>Emails:</h3>
          {emailsAsDivs}
        </div>
        <div>
          <h3>Licenses:</h3>
          {licensesAsDivs}
        </div>
      </div>
    );
    allObjectsHTML.push(objectAsHTML);
  });

What this function does in each iteration:

  • Use the helper function to map the emails,licenses arrays.
  • Map the rest of the key:value pairs in the object.
  • Push the mapped object to the allObjectsHTML array that will contain all the mapped objects.

And for the last step

Now all you need to do is that in your JSX code you return:

 return (
    <>
      {allObjectsHTML.map((obj,index) => (
        <div key={"bigObj" index}>{obj}<hr/></div>
      ))}
    </>
  );

This returns a mapped version of the allObjectsHTML.

This is the codeSandbox of my code.

And in case you want to check if it works on many objects in your array: second codeSandbox.

Note: If you know for sure that you have just one object in the myReturnedArray - then you don't need to use forEach. See this code.

CodePudding user response:

The initial format of your data is flawed, it's not a JS syntax. To get it done properly first you have to make it a proper data container. For this kind of task you don't need arrays, you have an object for that.

  const data = {
    id: 'stuff',
    location: 'stuff2', 
    address: 'stuff5',
    phone_numbers: ['stuff3','stuff4']
  }

Then in your React Components return section you may ve it done like this:

const {id, location:dataLoc, address, phone_numbers:phNums} = data
const [num1, num2] = phNums

return (
    <div>{dataLoc}</div>
    <span>{address}</span>
    //etc
)

I also reformatted yopur code a bit to meet the JS naming conventions. We use camelCase here, so no phone_numbers (snake_case is for Py)but phNum.

CodePudding user response:

You don't have a name property in your array items. Here is an example of code with your data that displays its content properly:

https://codesandbox.io/s/vigorous-euclid-nzbcp0?file=/src/App.js:24-283

  • Related