jforaker / react-accordion-with-header

React accordion component with flexbox header
https://react-accordion.xyz
16 stars 18 forks source link

Accordion resets on state change #6

Closed jreynolds12 closed 6 years ago

jreynolds12 commented 6 years ago

Hi,

The accordion works great apart from when I want to change the state in my project. Whenever the state is changed (anywhere in the project, not just the accordion), it resets itself by closing all panels.

I have an actionCallback setup for when all panels have been viewed. At the end of this, I want to use setState() but this is where the problem happens. The project has multiple interactions, which trigger other content being revealed. Once the accordion has been viewed, I change the state to do this. When the last panel is clicked on however, the accordion is resetting itself.

accordionChange (panels) {
        let seen = this.state.seen
        panels.forEach((panel, i) => {
            if(panel.open){
                seen[i] = true;   
            } 
        })

        if (seen.every(val => val === true)) {
            this.setState({ seen })
        }
    }
jforaker commented 6 years ago

Hi @jreynolds12 - very interesting. I think I get it, but can you record a video or gif of the interaction (assuming there is no private data)? This would help me to realize the issue.

Just so I understand - when your code calls this.setState({ seen }) it closes all panels?

Are you able to post a code block that shows how the parent component that controls this.state.seen has <AccordionWithHeader/> nested?

I think I get it, I'll try and reproduce and dig in (this week).

jreynolds12 commented 6 years ago

Thanks for the reply, unfortunately we decided to use a different accordion as we were under time pressure.

Yes, seen was essentially an array with boolean values and once all slides had been seen, then this.setState() would be called. If I had any panel open and set the state somewhere else in the page (such as whether the menu is open or not), this would also close the accordion or have the appearance of resetting it. Apologies for not providing more code but hopefully you can dig a bit deeper and replicate the issue.

jforaker commented 6 years ago

Thanks for the report @jreynolds12, I'm gonna check it out. I'll let you know here if I find a fix, just in case you are interested in using it again in the future.

ferryarman commented 6 years ago

@jforaker I'm currently using your component & I guess this could be the issue that has been reported earlier: accordion-auto-reset

And, here's my implementation. I've removed actionCallback prop & added key on the element tags, but seems the issue kept appearing

<AccordionWithHeader multipleOkay={false} firstOpen={true}>
  {Object.keys(orderDetails.body).map((orderNo, index) => {
    return (
        <AccordionNode key={`node${orderNo}`}>
          <AccordionHeader key={`header${orderNo}`} style={{padding: '5px 0', borderTop: 'solid 1px #eee', borderBottom: 'solid 1px #eee', color: 'blue'}}>
            Header {index+1}
          </AccordionHeader>
          <AccordionPanel key={`panel${orderNo}`} className="accordion-panel">
            <section key={`section${orderNo}`}>
              Description {index+1}
            </section>
          </AccordionPanel>
        </AccordionNode>
    );
  })}
</AccordionWithHeader>
jforaker commented 6 years ago

Thanks for the report @ferryarman - i'm out of town on vacation now, will fix when I get back and let you know

jforaker commented 6 years ago

Thanks all for the feedback.
Just published a new version 0.1.1 that addresses the above issue.

npm i react-accordion-with-header@latest

(In keeping up with React 16 paradigms, I moved away from componentWIllReceiveProps and refactored the component to allow for external control. This fixed the state change bug, and also did not introduce any breaking changes.)