Home > Enterprise >  Making the state of a component affect the rendering of a sibling when components are rendered itera
Making the state of a component affect the rendering of a sibling when components are rendered itera

Time:10-23

I have the following code:

export default function Parent() {
    const children1 = someArrayWithSeveralElements.map(foo => <SomeView />);
    const children2 = someArrayWithSeveralElements.map(foo => <SomeCheckbox />);

    return (<>
        {children1}
        {/*Some other components*/}
        {children2}
    </>)
};

For a given element foo, there is a SomeView component that is conditionally rendered based on the state of a SomeCheckbox. I'm having trouble figuring out a way to have the state from the checkbox affect the rendering of the sibling view component.

Normally the solution would be to just declare the state hook in the parent component and pass them down to each child, but since the siblings are rendered via foreach loops it's impossible to do so.

My current solution is to also generate the state hooks for each foo in a loop as well, but that feels a bit hacky since it's better to avoid creating hooks inside of loops (it's worth nothing that someArrayWithSeveralElements is not intended to change after mounting).

Is there a more elegant alternative to solve this?

CodePudding user response:

export default function Parent() {
    const [states, setStates] = React.useState([]);
    const children1 = someArrayWithSeveralElements.map((foo, i) => <SomeView state={states[i]} />);
    const children2 = someArrayWithSeveralElements.map((foo, i) => {
        const onStateChange = (state) => {
            setStates(oldStates => {
                const newStates = [...(oldStates || [])]
                newStates[i] = state;
                return newStates;
            })
        }
        return <SomeCheckbox state={states[i]} onStateChange={onStateChange} />;
    });

    return (<>
        {children1}
        {/*Some other components*/}
        {children2}
    </>)
};

Use states in the parent componet. Note: the element of states may be undefined.

CodePudding user response:

The solution is what you side, you need to create a state in the parent component and pass it to the children. and this will work for single component or bunch of them, the difference is just simple: use array or object as state.

const [checkboxesStatus, setCheckboxesStatus] = useState({// fill initial data});

const children1 = someArrayWithSeveralElements.map(foo =>
  <SomeView 
    visibile={checkBoxesStatus[foo.id]}
  />);
  
const children2 = someArrayWithSeveralElements.map(foo =>
  <SomeCheckbox
    checked={checkBoxesStatus[foo.id]}
    onChange={// set new value to foo.id key}
  />)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related