smapiot / piral

🚀 Framework for next generation web apps using micro frontends. ⭐️ Star to support our work!
https://piral.io
MIT License
1.71k stars 127 forks source link

how to useGlobalState in pilet #717

Closed ayaoshu closed 1 month ago

ayaoshu commented 1 month ago

Bug Report

For more information, see the CONTRIBUTING guide.

Prerequisites

Environment Details and Version

Package Version:^1.6.1, OS: mac, Browser: chrome

Description

when i using 'useGlobalState' in pilet , be like this error: TypeError: Cannot destructure property 'state' of 'useGlobalStateContext(...)' as it is undefined.

Expected behavior

Just like using ’useGlobalState‘ in piral

FlorianRappl commented 1 month ago

This is not a bug. You cannot import piral / your app shell in a pilet. The pilet does not depend on those.

Any app shell is just there for development purposes. Thus only the types are available.

Long story short:

Hope that helps!

ayaoshu commented 1 month ago

The situation is as follows. I registered slot [slotA] in [piletA], and [slotA] behaved normally in [app shell]. Now I want to use it in [piletB], I am using <ExtensionSlot name="slotA />", because [ExtensionSlot] relies on [useGlobalState], the above error occurs. I want to know, how can I use slotA in piletB correctly?

FlorianRappl commented 1 month ago

What you do is you import from piral / piral-core. These packages are not available in your pilet.

Please follow the documentation. It specifically tells you to use the Extension component living on the pilet API.

So it's not an import - you grab it from the inserted piral prop on your exposed components or by forwarding it (usually already wrapped to the specific slot name - but that's up to you).

toninospiderman123 commented 1 month ago

Hi FlorianRappl,

I think that have something like useGlobalPiletApi inside Pilet is really helpfull also to avoid to pass App (PiletAPI) prop for each nested components inside registered page or extension, because in different Pilets i have created a react context to do this.

Because today if i don't create a react context inside pilet, result is:

setup(app) {
app.registerPage("/page", Page)
}

const Page => (app) = {
   return <div>
   <Widget app={app} />
   <Widget2  />
   </div>
}

const Widget => (app) => {
const user = app.getUser()
return <div>
{user ? user.name : ""}
</div>
}

when with a useGlobalPiletApi i could use directly inside the component where i need to use

const Widget => () => {
const app = useGlobalPiletApi()
const user = app.getUser()
return <div>
{user ? user.name : ""}
</div>
}

Also if i have to use ExtensionA inside piletB and ExtensionA need to use PiletAPI to get user and do API request that need authentication i need to pass app as props to ExtensionA.

I suggest to take in consideration to add this, that at the end is the same thing that the App shell do with useGlobalState.

FlorianRappl commented 1 month ago

We will not add it - you can already add this yourself (remember that you can share any package - so you can also share, e.g., piral-core).

Furthermore, you don't have to pass on piral / any prop. You can just wrap it in your setup function in a context - and then useContext. To simplify this there is also the piral-hooks-utils package. It comes with a provider and a hook.

There are plenty of options and Piral won't decide here what to do for you - this is your choice as this is an architectural decision.

Keep in mind @toninospiderman123 that having such tight coupling to your app shell is an anti-pattern. It will make your pilets unnecessarily coupled to the app shell. That's why most examples that you see from us use / wrap the Piral specific things in the setup function. This way, you'll avoid the coupling and you get clean components - no extra things needed.

toninospiderman123 commented 1 month ago

Maybe you didn't get what i wrote.

This is my pilet (example from Piral documentation)

export function setup(app: PiletApi) {
  app.registerPage('/my-page', Page);
}

if my Page is a complex React component builded with other nested react component don't you think that could be boring passing the app property between all these components? Or maybe do you write only one big component (that is a bad practice) and so for you is not a problem? Don't you think that could be boring each time install piral-hooks-utils and wrap all the registered pages with the provider inside this library?

As i saw Piral is basically for a React developer, so what i'm asking is not something only for me like you wrote (There are plenty of options and Piral won't decide here what to do for you - this is your choice as this is an architectural decision.) but, from my point of view (and also from the point of view of who opened this issue i think), this cover a need of a React developer.

FlorianRappl commented 1 month ago

I do not get your aggressive tone.

Please read my message carefully - I think I got your point but from my perspective you did not get all the options I offered. You only went in to just not using the last / most clean option I've listed.

Why not pick the first option? It's as simple as sharing a package from your shell. Teams can then just import functions anywhere.

Final point:

How is installing one package boring? Companies we work with usually have a template for their teams - so nothing extra needs to be installed. For the wrapping you can use the HOC - so no need to do many steps. Instead of MyPage you just write withPiralContext(MyPage) - I don't think that's so much extra work.

toninospiderman123 commented 1 month ago

I'm sorry Florian if I seemed aggressive, it wasn't my intention.

We have two different approaches and I accept that.

I'm sure I'll find an alternative way to get to the result, in any case thanks for your availability.

FlorianRappl commented 1 month ago

Yes, no problem ❤️ - for such discussions I usually prefer chat or call; it's easier to show things / avoid misunderstandings (this mostly refers to my own messages).

As mentioned the idea is / was to provide that - just you need to opt-in. You can now decide if that opt-in is something that every team / pilet needs to do (e.g., by installing the package / wrapping the component in a HOC) or if that's provided by your Piral instance (e.g., by sharing the package).

In any case let me know if there are problems with the way you've selected. Happy to have you covered!