Open Antonio-Laguna opened 4 years ago
Hi there! :)
You're right, there could definitely be more examples about use cases - especially with the Async Actions. I've been meaning to make a short and quick video series about it too.
So basically, what it seems you're doing is making use of the both postActionHook
and making use of the result.payload
- where usually that is the choice that you need to make, which ever one suites the situation that you are in.
If you make use of postActionHook
you should just be getting your pages
from your ItemsStore
using useStoreState
in your component.
You also still use useBeckon
to trigger and watch the execution state of your action in your UI, as you've done.
So what you could do is:
export function HomePage() {
const pages = ItemsStore.useStoreState(s => s.pages);
const [finished, result] = usePages.useBeckon();
if (!finished) {
return (
<div>
Loading...
</div>
);
}
if (result.error) {
return <div>{result.message}</div>;
}
return (
<div>
<ul>
{pages.map(page => (<li key={page.index}>{page}</li>))}
</ul>
</div>
);
}
The other option would be to not make use of postActionHook
and just make use of the result directly, as you've done. I know it feels dirty, but its the only way to encapsulate the full state of a running async action. You could make it look slightly less messy like so:
export function HomePage() {
const [finished, result] = usePages.useBeckon();
if (!finished) {
return (
<div>
Loading...
</div>
);
}
if (result.error) {
return <div>{result.message}</div>;
}
// Typescript guarentees that this is now definitely the
// non-undefined payload since "result.error" = false
const pages = result.payload;
return (
<div>
<ul>
{pages.map(page => (<li key={page.index}>{page}</li>))}
</ul>
</div>
);
}
Or, of course pull out the payload earlier (cleanest looking but you lose some Typescript goodness):
const [finished, { error, message, payload: pages }] = usePages.useBeckon();
if (!finished) {
return (
<div>
Loading...
</div>
);
}
if (error) {
return <div>{message}</div>;
}
// Typescript unfortunately isn't smart enough to infer that "pages" is
// non-undefined here because we separated it out earlier
return (
<div>
<ul>
{pages.map(page => (<li key={page.index}>{page}</li>))}
</ul>
</div>
);
So, you were actually already kinda doing things the Pullstate™ way :)
I know it feels a little verbose, but it definitely beats keeping track of all that state for each action. If you want you could also give the newer React Suspense stuff a go which should feel less verbose and more declarative - (https://lostpebble.github.io/pullstate/docs/async-action-use#react-suspense-read-an-async-action)
Wow, thanks for the insights! I think that's useful!
Hi there!
I've been looking for some time for a decent alternative and less convoluted than Redux and I was ecstatic when I saw your module. Looks really nice!
I went through the docs and tried implementing it but felt a tad odd. I think my case is really straightforward and realized some people could run into this same pitfall or wonder so it could do for good examples that could enhance the docs/code.
Here's an "entity" which is a "page":
Then on the view, I want to render this list of pages:
However, it feels a bit convoluted and the
result.payload
feels kind of dirty to me which is what got me thinking if we were doing it right.