smapiot / piral

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

how to useGlobalState in pilet #717

Closed ayaoshu closed 6 days ago

ayaoshu commented 6 days 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 6 days 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 6 days 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 5 days 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 day 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 13 hours 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 5 hours 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.