I will be posting multiple types of Block
components in a vertical list in random orders and conditions. The blocks will be placed according to list values where list items will be inserted or deleted at any time. I need to store the reference of all the blocks in the exact order of their position in the parent element. The list of the references of the blocks should also be updated when the elements get updated/removed.
import React, { Fragment } from "react";
...
type Blocks = Block1 | Block2 | Block3;
interface Props {
data: ListData[];
}
interface State {
data: ListData[];
}
export default class Page extends React.Component<Props, State> {
state: State;
private blocks: Blocks[] = [];
constructor(props: Props) {
super(props);
this.state = {
data: props.data
};
}
private addListDataItems(): void {} // Add `ListData` items randomly
private removeListDataItems(): void {} // Remove `ListData` items randomly
render(): JSX.Element {
return <>
<div className="page">
{this.state.data.map((li: ListData, i: number) => <Fragment key={i}>
{((i % 10) === 0) && <>
<Block1
ref={(e: Block1): void => {
this.blocks[ /* Insert reference according to it's position in the parent element */ ] = e;
}}
...
/>
</>}
{(
// Some conditional Logic Here
) && <>
<Block2
ref={(e: Block2): void => {
this.blocks[ /* Insert reference according to it's position in the parent element */ ] = e;
}}
...
/>
</>}
{(
// Some conditional Logic Here
) && <>
<Block3
ref={(e: Block3): void => {
this.blocks[ /* Insert reference according to it's position in the parent element */ ] = e;
}}
...
/>
</>}
</Fragment>
</div>
</>;
}
}
2
Answers
The best solution would probably depend on what you need to do with the references afterwards. Since you’re looking for an array in order, I’m going to assume you’ll need to iterate over them top to bottom.
I’d propose a sparse array as your best option here: each
ListData
item in thethis.state.data
array can result in 0, 1, 2, or 3Block
being added to your array, so the resulting sparse array of refs could look like[ref, ref, undefined, ref, undefined undefined, ref, ref, ref, ...]
.To obtain that array, simply use a multiple of
i
as your index:Don’t forget to also reset your ref array at the top of the render function to avoid preserving old refs when re-rendering.
And when you need to iterate over your blocks, just skip the falsy ones:
Or use array functions since they already skip empty elements in a sparse array:
Clarification: I represented a sparse array as having either a
ref
orundefined
in each item, but a sparse array is an actual thing in JS when an item hasn’t been defined ever (or has beendelete
d). And the console representation of a sparse array looks like thisThe best solution would probably depend on what you need to do with the references afterwards. Since you’re looking for an array in order, I’m going to assume you’ll need to iterate over them top to bottom.
If you need to have a compact (regular) array, you should try and think more in JavaScript terms and less React. React is just JS after all.
For example, you could have a counter to remember the indices of your array:
Or if manipulating JSX outside of the return of the render function is too odd looking, you could just compute the conditions beforehand