Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multiple instance on the same page #204

Open
clodoveo opened this issue Oct 17, 2024 · 9 comments
Open

multiple instance on the same page #204

clodoveo opened this issue Oct 17, 2024 · 9 comments

Comments

@clodoveo
Copy link

I'm trying to develop a widget that ideally should be instantiated multiple times on the same page. However, it is only being rendered for the first one in the list. Is it possible to have more than one with the same name but for example different IDs?

@bmomberger-bitovi
Copy link
Contributor

bmomberger-bitovi commented Dec 6, 2024

Hi @clodoveo,

Can you show me some example code? I've definitely done experiments in the past with multiple instances of the same component and didn't have this problem, so I might be able to find the root of the problem if I see how you're using it.

@subramanian-iouring
Copy link

subramanian-iouring commented Jan 10, 2025

@bmomberger-bitovi
While using same web component in html with different params, facing issues like collapse the data params between web components.

<div class="menu1"> 
  <web-app name="sam" age="32"></web-app>
</div>
<div class="menu2">
  <web-app name="jack"></web-app>
</div>

From above code, we are allowing any one of div to DOM, while showing 1st div, 2nd div is not DOM.
So when we try to remove 1st div and append 2nd div in DOM. we are getting age props here too.

@bmomberger-bitovi
Copy link
Contributor

What library are you using to remove and append these divs? Is it one with a virtual DOM? It's possible that the library is reusing the same web-app element for efficiency, which would lead to the condition you're describing.

@subramanian-iouring
Copy link

@bmomberger-bitovi
Actually not using any library, based on boolean i tried to show the web-app in react.

@bmomberger-bitovi
Copy link
Contributor

bmomberger-bitovi commented Jan 13, 2025

You tried to show the web-app in React? React is a library that uses virtual DOM just like I described above.

Here, this pen shows how the instance swap with regular DOM manipulation does not leave a stale value for age: https://codepen.io/bmomberger-bitovi/pen/WbezqzM

Edit: If you see this problem in React, try generating a unique key for every instance of <web-app> that you show or hide. I don't have the bandwidth to test this right now, but it is the sensible first thing to try.

@subramanian-iouring
Copy link

@bmomberger-bitovi
Am using redux for state management with react, and that is web component.
when i open r2wc element in DOM and we store something in redux and removed the r2wc web element in DOM.
Again when i open r2wc component in DOM. is existing redux value will persist?

Am facing issue in this scenario. the redux values are persists.

@bmomberger-bitovi
Copy link
Contributor

@subramanian-iouring When you initialize your redux Provider, where is your store coming from?

If it's always the same store object being passed to the redux Provder, then it will have the same values even if you remove the React root and re-create it.

@subramanian-iouring
Copy link

subramanian-iouring commented Jan 16, 2025

@bmomberger-bitovi

Here, is the exact code. which am using redux Provider. is any other way to resolve this issue?

const AppWrapper = (props: any) => {
    const { children } = props;

    const [
        domRef, setDomRef
    ] = useState<HTMLStyleElement>();

    const cache = useMemo(() => {
        if (domRef)
            return createCache({ key: "css", prepend: true, container: domRef });
        return null;
    }, [
        domRef
    ]);

    const getRef = useCallback((ref: HTMLStyleElement | null) => {
        if (ref)
            setDomRef(ref);
    }, [
    ]);

    return <StyledEngineProvider injectFirst>
        <Provider store={store}>
            <style ref={getRef}></style>
            <link rel="stylesheet" href={`${AppSettings.publicUrl?.trim()}/static/css/nxtoption-sdk.css`} />

            {cache !== null ? <CacheProvider value={cache}> {children} </CacheProvider> : null}
        </Provider>
    </StyledEngineProvider>;
};

const AppContainer = (props: any) => {
    if (isEmpty(props))
        return <div>Invalid payload</div>;

    return <AppWrapper>
        {
            {
                [ APP_MODE.HOME ]: <App {...props} />,
                [ APP_MODE.ANALYZE ]: <App {...props} isAnalyze={true} />
            }[ props.mode ]
        }
    </AppWrapper>;
};

const WebAppComponent = r2wc(AppContainer, {
    shadow: "open",
    props: {
        payload: "string",
        eventcallback: "function"
    }
});

class WebApp extends WebAppComponent {
    constructor() {
        super();
        loadFont("NxtOption-Icon-Font", `${AppSettings.publicUrl?.trim()}/assets/icons/nxtoption.ttf`);
        loadFont("NxtOption-Regular", `${AppSettings.publicUrl?.trim()}/assets/fonts/nxtoption-regular.woff2`);
    }

    connectedCallback() {
        console.log("connectedCallback");
    }

    disconnectedCallback() {
        console.log("disconnectedCallback");
    }
}

customElements.define("web-app", WebApp);

// Using web-app in another react application

<div class="menu1"> 
  <web-app mode="home"></web-app>
</div>
<div class="menu2">
  <web-app mode="analyze" {...props} ></web-app>
</div>

@bmomberger-bitovi
Copy link
Contributor

Your code shows <Provider store={store}> but doesn't have any other reference to store. I am assuming that it's imported from another module.

What I would do instead is to have that module export a function like getInitialStore() that returns the initial state of your redux store, and then in your AppWrapper:

const [store] = useState(getInitialStore());

useState() is used here because it will not revert to the initial store on component update, only on component mount.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants