2

I'm still figuring out how React works and renders its components, and have had this question for a while - supposing I have a Component D that is imported into components B & C, and both B & C are imported into component A. So the component tree would look as follows:

Component A

  • Component B
    • Component D
  • Component C
    • Component D

It seems like Component D is being imported twice into Component A (albeit indirectly) via Components B & C. I wonder if this creates performance issues and whether I should make attempts to ensure that Component D is only included once from Component A's perspective (I guess using the Context API can resolve this?)

Abhishek Tirkey
  • 435
  • 1
  • 6
  • 12
  • You can import is to component A, and pass it as a prop to components B and C. – YTG Jan 20 '21 at 09:27
  • yes this might be issue, this is why you can use redux to resolve this problem. You can check the following answer. https://stackoverflow.com/questions/65785994/how-to-share-data-from-one-react-native-component-to-another-component/65786436#65786436 – S.N.B Jan 20 '21 at 09:35
  • I think with the way webpack works, it's not going to be an issue. You can check your build files to see if you're getting two copies of component D. I thought webpack would save component D as a variable and then access that variable whenever it needs to. I could be wrong though. – JakeAve Jan 20 '21 at 13:44

1 Answers1

1

We are talking about two different topics here:

  1. importing same module multiple times
  2. using shared or individual state for multiple times imported module (you mentioned the Context API)

1. importing same module multiple times

Importing the same module inside multiple other modules is totally ok. Think about we are importing React in every file.

Here is a nice answer regarding this topic: ES6 import duplicates

Additionally, below I add an example with your nested structure
(B and C both import D, A imports B and C).

Here D is passed up from both B and C to A, so that both imports can be compared inside of A, and as you can see, both D are the same,
(console output: D_from_B === D_from_C: true):

// -- ComponentD.jsx --

import React from 'react';
export default function ComponentD(props){
    return (<span>imported module ComponentD</span>);
};

// == ComponentC.jsx ==

import React, { useEffect } from 'react';
import ComponentD from './ComponentD';

export default function ComponentC( props ){
    useEffect(()=>{ props.passSub( ComponentD ); },[]);
    return (<div>
        <p>ComponentC</p>
        <ComponentD />
    </div>);
};

// == ComponentB.jsx ==

import React, { useEffect } from 'react';
import ComponentD from './ComponentD';

export const ComponentB = (props)=>{
    useEffect(()=>{ props.passSub( ComponentD ); });
    return (<div>
        <p>ComponentB</p>
        <ComponentD />
    </div>);
};

// == ComponentA.jsx ==

import React, { useEffect } from 'react';
import { ComponentB } from './ComponentB';
import ComponentC from './ComponentC';

let componentDfromB = null;
let componentDfromC = null;

export const ComponentA = (props)=>{

    useEffect(()=>{
        console.log('D from B === D from C:', componentDfromB === componentDfromC);      // <--- true
        console.log('Object.is(DB, DC):', Object.is(componentDfromB, componentDfromC));  // <--- true
    });

    return (<div>
        <ComponentB passSub={ function( Sub ){ componentDfromB = Sub; } } />
        <ComponentC passSub={ function( Sub ){ componentDfromC = Sub; } } />
    </div>);
};

Remark: this code shall only illustrate the point. This approach usually does not work properly in a normal App (e.g. setting componentDfromB inside the callback.)

2. using shared or individual state

So, the imported modules are the same. But the state is not.
The imported "thing" is a React.Component, not a React.Element, which is similar to the relation class vs. instance.

If the React.Component D was imported, it is instantiated inside the component which has imported it, so each importing component (B and C) has its own instance of D, with a separate, own state. But that is usually exactly what you want.

If you want to share the same state across different components, you would use techniques like context, redux, passing props, ... I think the details are outside the scope of this question.

So what about performance...

I would say performance is just no issue here, not regarding module import, and not regarding state.

I think nobody really chooses one over the other here discussed approach for performance reasons, but for data structure or code cleanliness (of course, a bad data structure might have a bad performance, but that's not the "fault" of the React-state).

If you are still curious about performance, I think that should be a separate, more specific question about something like "performance state vs. props".

kca
  • 4,856
  • 1
  • 20
  • 41