skip to Main Content

The answer in Unmitigated helped me, if you are searching from google scroll down

order:
[ "567", "645", "852", "645", "852", "852", ]

database:
[ { "userId": 567, "userName": "tjk23", "department": "Sales", "remarks": "" }, { "userId": 645, "userName": "gfn23", "department": "Sales", "remarks": "" }, { "userId": 852, "userName": "dan24", "department": "Sales", "remarks": "", } ]

Currently it’s mapping fine with the database array, but only displays 3 of the DisplayCard. I need it to display 6 times and also in the order of the 6 in order array

{database.map((data, index) => { return <DisplayCard data={data} key={index}/> })}

How do I make it map using the sequence of the order array without changing too much code? As the DisplayCard is used in multiple places I would like to not modify it

I tried using

{order.map((database.data, index) => { return <DisplayCard data={database.data} key={index}/> })}

and expected it to use the sequence of the order array, and get the data from the corresponding userId in the database array

But what actually resulted is an error but I don’t know why

Edit for Unmitigated:
Here is a minimally reproducible example, I removed the API call and external DisplayCard reference and have everything fit into this snippet

export function Minimal() {
    var lookup;

    const order= [ "567", "645", "852", "645", "852", "852", ];

    const database = [ { "userId": 567, "userName": "tjk23", "department": "Sales", "remarks": "" }, { "userId": 645, "userName": "gfn23", "department": "Sales", "remarks": "" }, { "userId": 852, "userName": "dan24", "department": "Sales", "remarks": "", } ];
    
    function DisplayCard({data}) {
        return <div>{data.userId}</div>;
      }

    return (<>

    {database?.length > 0
        ? lookup = Object.fromEntries(database.map(o => [o.userId, o]))
        (
            <>
                {order.map((userId, index) => {
                    return <DisplayCard data={lookup[userId]} key={index} />                  
                })}     
            </>
        ) :
        (
            <div className="empty">
                <h2>No records found</h2>
            </div>
        )}
    
</>)}

3

Answers


  1. You can create an object that maps each userId to an object in the array, then access the values from this lookup object when using order.

    let lookup = Object.fromEntries(database.map(o => [o.userId, o]));
    // ...
    {order.map((id, index) => <DisplayCard data={lookup[id]} key={index}/>)}
    

    Example:

    function DisplayCard({data}) {
      return <div>{data.userName}</div>;
    }
    
    function App() {
      let order = [ "567", "645", "852", "645", "852", "852", ];
      let [database, setDatabase] = React.useState([ { "userId": 567, "userName": "tjk23", "department": "Sales", "remarks": "" }, { "userId": 645, "userName": "gfn23", "department": "Sales", "remarks": "" }, { "userId": 852, "userName": "dan24", "department": "Sales", "remarks": "", } ]);
      let lookup = Object.fromEntries(database.map(o => [o.userId, o]));
      return (
        <div>
          {order.map((id, index) => <DisplayCard data={lookup[id]} key={index}/>)}
          <button onClick={() => setDatabase([{userId: 567, userName: 'changed 567'}, {userId: 645, userName: 'changed 645'}, {userId: 852, userName: 'changed 852'}])}>Change state</button>
        </div>
      );
    }
    
    ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <div id="root"></div>
    Login or Signup to reply.
  2. {
      order.map((id, index) => {
        const target = datebase.find(item => item.userId === id)
        return target ? <DisplayCard data={target} key={index} /> : null
      })
    }
    
    Login or Signup to reply.
  3. What you really want is not map, it’s a filtering on database array. The map method is not used like you are thinking see definition: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

    I strongly believe that this is a way without changing too much code

    Step 1: Filter database array according to the ids on order array

    Step 2: Now you can use the database array filtered

    let resultsFiltered = database.filter(item => order.includes(item.userId))
        
    {resultsFiltered.map((data, index) => { return <DisplayCard data={data} key={index}/>})}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search