0

I have an array of objects which I'm rendering by section - see title of each object "Price", "Sectors and Charges" etc.

This populates a mini modal where users can select options to update rendered columns basically a filter.

The selection of the items are working however if I make a selection of the first item "0" all sections with the first option are selected.

How can I store the selection from each object into the selectedOptions array?

Please note I'm using react js and styled components, I've not added the styled component code.

Data:

const columnsData = [
    {
        title: 'Price',
        options: [
            {
                label: 'Daily Change'
            },
            {
                label: 'Price'
            },
            {
                label: 'Price Date'
            },
            {
                label: 'Volatility Rating'
            }
        ],
    },
    {
        title: 'Sectors and Charges',
        options: [
            {
                label: 'Sector'
            },
            {
                label: 'Asset Class'
            },
            {
                label: 'AMC'
            },
        ],
    },
    {
        title: 'Cumulative Performance',
        options: [
            {
                label: '1 month'
            },
            {
                label: '6 months'
            },
            {
                label: '1 year'
            },
        ],
    },
]

Code:

const EditColumns = ({active, onClick}) => {
    const [selectedOptions, setSelectedOptions] = useState([0, 1, 2]);

    const update = () => {
        onClick();
    }

    const updateSelection = (z) => {
        setSelectedOptions(selectedOptions.includes(z) ? selectedOptions.filter(j => j !== z) : [...selectedOptions, z]);
    }

    return (
        <Wrap onClick={() => update()}>
            <CTA>
                <SVG src="/assets/svgs/btns/edit.svg" />
                <span>Columns</span>
            </CTA>
            {active &&
                <Dropdown>
                    <Head>
                        <span className="title">Edit Columns</span>
                        <span>Select the columns you would like to see</span>
                    </Head>
                    <Body>
                        {columnsData.map((item, i) => {
                            return (
                                <Section key={i}>
                                    <SectionHead>
                                        <span className="title">{item.title}</span>
                                        <span>Select all</span>
                                    </SectionHead>
                                    <SectionList>
                                        {item.options.map((child, z) => {
                                            const selected = selectedOptions.includes(z);                                       
                                            return (
                                                <li key={z} className={classNames({selected})} onClick={() => updateSelection(z)}>
                                                    <span>{child.label}</span>
                                                </li>
                                            )
                                        })}
                                    </SectionList>
                                </Section>
                            )
                        })}
                    </Body>
                </Dropdown>
            }   
        </Wrap>
    )
}

export default EditColumns;

1 Answer 1

1

Your section lists are all sharing the same state variable, so any changes will be applied to all of them. You could fix this either by constructing a more complex state object which more closely resembles the structure of columnsData, or making each SectionList its own component with its own state. What you decide to do will depend on the degree to which the EditButtons component actually needs access to the whole state.

The second approach might look something like this:

const EditColumns = ({active, onClick}) => {
    const update = () => {
        onClick();
    }

    return (
        <Wrap onClick={() => update()}>
            <CTA>
                <SVG src="/assets/svgs/btns/edit.svg" />
                <span>Columns</span>
            </CTA>
            {active &&
                <Dropdown>
                    <Head>
                        <span className="title">Edit Columns</span>
                        <span>Select the columns you would like to see</span>
                    </Head>
                    <Body>
                        {columnsData.map((item, i) => {
                            return (
                                <Section key={i}>
                                    <SectionHead>
                                        <span className="title">{item.title}</span>
                                        <span>Select all</span>
                                    </SectionHead>
                                    <SectionList options={item.options}/>
                                </Section>
                            )
                        })}
                    </Body>
                </Dropdown>
            }   
        </Wrap>
    )
}
const SectionList = ({options}) => {
    const [selectedOptions, setSelectedOptions] = useState([0, 1, 2]);

    const updateSelection = (z) => {
        setSelectedOptions(selectedOptions.includes(z) ? selectedOptions.filter(j => j !== z) : [...selectedOptions, z]);
    }

    return (
        <SectionListContainer>
            {options.map((child, z) => {
                const selected = selectedOptions.includes(z);                                       
                return (
                    <li key={z} className={classNames({selected})} onClick={() => updateSelection(z)}>
                        <span>{child.label}</span>
                    </li>
                )
            })}
        </SectionListContainer>
    )
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you will try this approach.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.