Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I bind a React Component to an Object in an Array?

I’m trying to make a Website which behaves like Windows/Ubuntu ect.
There I have a Desktop and n amount of Apps which have their own state (Position, Size).

The specifications of the opened Apps are stored as Objects in a useState Array.
If an App gets closed, i want to remove the according entry out of the Array.

The Problem I now encounter is that if I close an App, the rendered Apps just get rearranged.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

For Example, I remove (close) the second Entry the Array.
Now the third Entry uses the App Component from the second App:

Problem

I render the Apps with a map function.


const [openedAppConfigs, setOpenedAppConfigs] = useState<AppConfigType[]>([
    { applicationTitle: "Application Title 1", zIndex: 1 },
    { applicationTitle: "Application Title 2", zIndex: 2 },
    { applicationTitle: "Application Title 3", zIndex: 3 },
  ]);

return (
      ...
      {
        openedAppConfigs.map((appConfig, i) => (
          <App key={i} zIndex={appConfig.zIndex} 
               applicationTitle={appConfig.applicationTitle}
               ...moreProps >
            <div />
          </App>
        ))
      }
      ...
)

But what I want to achieve is something like this:

Expected

I thought about creating Instances of the App Component by turning it into a Class and then saving it in the Array of opened Apps.
I haven’t jet worked with classes in JS but i know Object Oriented Programming from Java.
Is that a good solution to achieve this, or are there better ways?

>Solution :

openedAppConfigs.map((appConfig, i) => (
  <App 
    key={i} // <------ PROBLEM
    zIndex={appConfig.zIndex} 
    applicationTitle={appConfig.applicationTitle}
    ...moreProps
  >
    <div />
  </App>
))

The problem is that you’re using the array index as the key. The purpose of keys is to tell react which element from one render corresponds to which element from the next render. So on one render react sees keys 0, 1, 2 with various props, and on the second render react sees keys 0 and 1 (with 1 having some very different props than it did last time). As a result, it removes element 2, and updates the props on 1.

To fix this, give each element a unique key. They keys could be in order or random, but each app needs to have its own key which never changes.

const [openedAppConfigs, setOpenedAppConfigs] = useState<AppConfigType[]>([
  { id: 0, applicationTitle: "Application Title 1", zIndex: 1 },
  { id: 1, applicationTitle: "Application Title 2", zIndex: 2 },
  { id: 2, applicationTitle: "Application Title 3", zIndex: 3 },
]);
// ...
openedAppConfigs.map((appConfig) => (
  <App 
    key={appConfig.id} 
    zIndex={appConfig.zIndex} 
    applicationTitle={appConfig.applicationTitle}
    ...moreProps
  >
    <div />
  </App>
))

Now, we go from keys 0, 1, 2 on one render to keys 0, 2 on the next. So react knows it needs to unmount the middle element, and not change any props.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading