@
@
@insighter2021-06-15 07:07:47
React
@insighter, 2021-06-15 07:07:47

How to prevent React from re-creating child components?

I am writing my own component for working with tabs. Tabs, in turn, are also React components and are generated dynamically in a loop.
I use the standard approach: a state is created (through useState) into which an array of tabs is written. As soon as a tab is removed or a new one is added, a new array is created in which the tab is added/removed. This array is then passed as a new state.

Everything works well, but when deleting a tab, Rect recreates all tabs after the deleted one, mistaking them for new objects.

How to tell the framework that these objects have already been created?

PS tried to prescribe key (generated sequential surrogate keys) does not work.
PPS when deleting a tab, a new array is created like this:

let tabsNewList = tabs.slice();
tabsNewList.splice(tabIndex, 1);
...
...
setTabs(tabsNewList);

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
insighter, 2021-06-15
_

I found the answer myself.
When comparing the old and new DOM, React compares the key field of the existing and new object, if the
field values ​​match, then the new object is discarded, otherwise the old object will be destroyed and completely replaced by the new one. Of course, key comparison is only a small part of the overall matching algorithm.
In my case, the components that are displayed in tabs can be of different types, and most often they are.
Therefore, React does not use comparison through key and removes the remaining bookmarks ( although! for some reason, if you create
tabs of the same type, they will be deleted anyway
)
The solution is found in using the Fragment component with a surrogate key Key
generation:

const [keyGenValue, setKeyGenValue] = useState(1);
    ...
    // генерим новое значение при открытии новой вкладки
    setKeyGenValue(() => {
        return keyGenValue + 1;
    });

Render generation:
<div className='workspace'>
    {views.map(
        (view, index) =>
        <Fragment key={view.key}>
            <div hidden={view !== selectedView}>
                    <h4>{view.caption}</h4>
                    <div>{buildView(view.name)}</div>
            </div>
        </Fragment>
    )}
</div>

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question