mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-03 19:43:27 +08:00
fix(accordion): moving to state-based re-rendering instead of calling forceUpdate to try to prevent race conditions
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
import type { ComponentInterface } from '@stencil/core';
|
||||
import { Component, Element, Host, Prop, State, Watch, forceUpdate, h } from '@stencil/core';
|
||||
import { Component, Element, Host, Prop, State, Watch, h } from '@stencil/core';
|
||||
import { addEventListener, getElementRoot, raf, removeEventListener, transitionEndAsync } from '@utils/helpers';
|
||||
import { chevronDown } from 'ionicons/icons';
|
||||
|
||||
@ -48,20 +48,19 @@ export class Accordion implements ComponentInterface {
|
||||
private headerEl: HTMLDivElement | undefined;
|
||||
|
||||
private currentRaf: number | undefined;
|
||||
/**
|
||||
* If true, the next animation will be skipped.
|
||||
* We want to skip the animation when the accordion
|
||||
* is expanded or collapsed on the initial load.
|
||||
* This prevents the accordion from animating when
|
||||
* it starts expanded or collapsed.
|
||||
*/
|
||||
private skipNextAnimation = true;
|
||||
|
||||
@Element() el?: HTMLElement;
|
||||
|
||||
@State() state: AccordionState = AccordionState.Collapsed;
|
||||
@State() isNext = false;
|
||||
@State() isPrevious = false;
|
||||
/**
|
||||
* Tracks whether the component has completed its initial render.
|
||||
* Animations are disabled until after the first render completes.
|
||||
* This prevents the accordion from animating when it starts
|
||||
* expanded or collapsed on initial load.
|
||||
*/
|
||||
@State() hasRendered = false;
|
||||
|
||||
/**
|
||||
* The value of the accordion. Defaults to an autogenerated
|
||||
@ -132,14 +131,14 @@ export class Accordion implements ComponentInterface {
|
||||
}
|
||||
|
||||
componentDidRender() {
|
||||
if (this.skipNextAnimation) {
|
||||
this.skipNextAnimation = false;
|
||||
/**
|
||||
* The initial render disables animations so framework-provided
|
||||
* values do not cause the accordion to animate. Force a repaint
|
||||
* so subsequent user interactions animate as expected.
|
||||
*/
|
||||
forceUpdate(this);
|
||||
/**
|
||||
* After the first render completes, mark that we've rendered.
|
||||
* Setting this state property triggers a re-render, at which point
|
||||
* animations will be enabled. This ensures animations are disabled
|
||||
* only for the initial render, avoiding unwanted animations on load.
|
||||
*/
|
||||
if (!this.hasRendered) {
|
||||
this.hasRendered = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,7 +314,12 @@ export class Accordion implements ComponentInterface {
|
||||
* of what is set in the config.
|
||||
*/
|
||||
private shouldAnimate = () => {
|
||||
if (this.skipNextAnimation) {
|
||||
/**
|
||||
* Don't animate until after the first render cycle completes.
|
||||
* This prevents animations on initial load when accordions
|
||||
* start in an expanded or collapsed state.
|
||||
*/
|
||||
if (!this.hasRendered) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -351,11 +355,6 @@ export class Accordion implements ComponentInterface {
|
||||
const value = accordionGroup.value;
|
||||
|
||||
const shouldExpand = Array.isArray(value) ? value.includes(accordionValue) : value === accordionValue;
|
||||
const shouldDisableAnimation = initialUpdate && shouldExpand;
|
||||
|
||||
if (shouldDisableAnimation) {
|
||||
this.skipNextAnimation = true;
|
||||
}
|
||||
|
||||
if (shouldExpand) {
|
||||
this.expandAccordion(initialUpdate);
|
||||
|
||||
Reference in New Issue
Block a user