mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-15 17:42:15 +08:00
fix(react): nav will remove components from the DOM (#25763)
Issue #: resolves #25753 ---------- <!-- Please refer to our contributing documentation for any questions on submitting a pull request, or let us know here if you need any help: https://ionicframework.com/docs/building/contributing --> ## Pull request checklist Please check if your PR fulfills the following requirements: - [x] Tests for the changes have been added (for bug fixes / features) - [ ] Docs have been reviewed and added / updated if needed (for bug fixes / features) - Some docs updates need to be made in the `ionic-docs` repo, in a separate PR. See the [contributing guide](https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation) for details. - [x] Build (`npm run build`) was run locally and any changes were pushed - [x] Lint (`npm run lint`) has passed locally and any fixes were made for failures ## Pull request type <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type, submit multiple pull requests if needed. --> Please check the type of change your PR introduces: - [x] Bugfix - [ ] Feature - [ ] Code style update (formatting, renaming) - [ ] Refactoring (no functional changes, no api changes) - [ ] Build related changes - [ ] Documentation content changes - [ ] Other (please describe): ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> When `IonNav` performs a pop operation (navigating to root, back, etc.) the views are not removed from the DOM. <!-- Issues are required for both bug fixes and features. --> ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - `IonNav` removes pages from the DOM when they are popped (navigate back, navigate to root, etc.) - Memoized constructing React delegate (was reconstructing on each render) ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> --------- Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
import type { FrameworkDelegate, JSX } from '@ionic/core/components';
|
||||
import { defineCustomElement } from '@ionic/core/components/ion-nav.js';
|
||||
import React, { useState } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
|
||||
import { ReactDelegate } from '../../framework-delegate';
|
||||
import { createReactComponent } from '../react-component-lib';
|
||||
@ -25,10 +25,10 @@ const IonNavInternal: React.FC<IonNavProps> = ({ children, forwardedRef, ...rest
|
||||
* Allows us to create React components that are rendered within
|
||||
* the context of the IonNav component.
|
||||
*/
|
||||
const addView = (view: React.ReactElement) => setViews([...views, view]);
|
||||
const removeView = (view: React.ReactElement) => setViews(views.filter((v) => v !== view));
|
||||
const addView = (view: React.ReactElement) => setViews((existingViews) => [...existingViews, view]);
|
||||
const removeView = (view: React.ReactElement) => setViews((existingViews) => existingViews.filter((v) => v !== view));
|
||||
|
||||
const delegate = ReactDelegate(addView, removeView);
|
||||
const delegate = useMemo(() => ReactDelegate(addView, removeView), []);
|
||||
|
||||
return (
|
||||
<IonNavInner delegate={delegate} ref={forwardedRef} {...restOfProps}>
|
||||
|
@ -9,7 +9,7 @@ export const ReactDelegate = (
|
||||
addView: (view: React.ReactElement) => void,
|
||||
removeView: (view: React.ReactElement) => void
|
||||
): FrameworkDelegate => {
|
||||
const refMap = new WeakMap<ReactComponent, React.ReactElement>();
|
||||
const refMap = new WeakMap<HTMLElement, React.ReactElement>();
|
||||
|
||||
const attachViewToDom = async (
|
||||
parentElement: HTMLElement,
|
||||
@ -24,17 +24,19 @@ export const ReactDelegate = (
|
||||
const componentWithProps = component(propsOrDataObj);
|
||||
const hostComponent = createPortal(componentWithProps, div);
|
||||
|
||||
refMap.set(component, hostComponent);
|
||||
refMap.set(div, hostComponent);
|
||||
|
||||
addView(hostComponent);
|
||||
|
||||
return Promise.resolve(div);
|
||||
};
|
||||
|
||||
const removeViewFromDom = (_container: any, component: ReactComponent): Promise<void> => {
|
||||
const removeViewFromDom = (_container: any, component: HTMLElement): Promise<void> => {
|
||||
const hostComponent = refMap.get(component);
|
||||
hostComponent && removeView(hostComponent);
|
||||
|
||||
component.remove();
|
||||
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user