lostpebble / pullstate

Simple state stores using immer and React hooks - re-use parts of your state by pulling it anywhere you like!

Home Page:https://lostpebble.github.io/pullstate

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Multiple async actions with one component

cyates81 opened this issue · comments

Hello,

I'm just getting started with React and coming from an Angular background. I have to admit that so far the learning curve on something as simple as implementing a global state object has been dumbfounding to me. In angular it's as simple as declaring and using a service.

Anyhow, I saw all the warnings about Redux and when I found this project it seemed much simpler and easier to understand. I already implemented an async action that pulls data from Google Firestore and updates my store state and displays it in a component. Great.

My first question is, what if I want to call multiple async actions in one component? I like how Apollo client returns objects rather than arrays so you can rename during destructuring. Is there a way to do this with pullstate?

For example:

const [ finished, result ] = getCart.useBeckon({});
const [ finished, result ] = getUser.useBeckon({foo:'bar'});

wouldn't work, but this would:

const {finished:cartFinished, result:cartResult} = getCart.useBeckon({});
const {finished:userFinished, result:userResult} = getUser.useBeckon({foo:'bar'});

One more question. If I wanted to keep Firestore in sync with the pullstate store, what's the recommended way of going about that? For example, any time there is an update to the pullstate store, I want it to do the same update on Firestore.

Hi @cyates81 ,

Glad its been helping you on your React journey to getting up and running quicker.

There is actually a currently undocumented - but very mature - way of doing this now. I've been playing around with it in my projects because I too prefer the object way of returning data, opposed to an array - especially in these kinds of cases.

But just to quickly show you a way to do it currently, you can actually name array destructuring variables whatever you wish. So instead of this:

const [ finished, result ] = getCart.useBeckon({});
const [ finished, result ] = getUser.useBeckon({foo:'bar'});

You can do this:

const [ getCartFinished, getCartResult ] = getCart.useBeckon({});
const [ getUserFinished, getUserResult ] = getUser.useBeckon({foo:'bar'});

But to show you the newer way, take a look at the changelog here: https://github.com/lostpebble/pullstate/blob/master/Changelog.md#1110

Basically you can now do something like:

const { isFinished: cartFinished, payload: cartPayload } = getCart.use({});
const { isFinished: userFinished, payload: userPayload } = getUser.use({foo:'bar'});

Or, how I prefer to use it (because it encapsulates the actions nicely, and because with TypeScript we getting better type cohesiveness on the object because we're not splitting up the object into its separate properties):

const getCartAction = getCart.use({});
const getUserAction = getUser.use({foo:'bar'});

// later...

<div>{getUserAction.renderPayload(({ user }) => <h1>{user.name}</h1>)}</div>

// or just

<div>{!getUserAction.error && <h1>{getUserAction.payload.user.name}</h1>}</div>

Here I make use of the utility function which is returned from use() - renderPayload(), which will either do nothing (if the result is not complete successfully), or it will run and return the result of the passed function.

One more question. If I wanted to keep Firestore in sync with the pullstate store, what's the recommended way of going about that? For example, any time there is an update to the pullstate store, I want it to do the same update on Firestore.

I think what you want is subsribe() - its what I use whenever I need to sync Pullstate's state into an external library. Take a look at the documentation here.

Hope that helps! Let me know if anything isn't clear enough. I'll need to update the documentation soon in any case with the new way of using async actions.

Ah, thank you! Yes that is much nicer.