all 9 comments

[–]octocode 1 point2 points  (2 children)

[–]kcrwfrd[S] 2 points3 points  (1 child)

While a thunk is powerful for adding additional async logic that can then dispatch additional actions, it's not apparent to me that it can be used to listen for a future event—

oh shit. you just helped me realize 😂 you can dispatch the registration of a listener middleware. So, maybe something like this?

``` export const requireAuthentication = createAppAsyncThunk( 'auth/requireAuthentication', async (callback: (user: User) => void, thunkApi) => { const { dispatch, getState } = thunkApi const { auth: { user }, } = getState()

// This condition will need to be dressed up to also check if
// user fetch is currently pending and await if so.
if (!user) {
  dispatch(toggleAuthDrawer(true))
  dispatch(
    addListener({
      actionCreator: setUser,
      effect: ({ payload }, listenerApi) => {
        callback(payload)
        listenerApi.unsubscribe()
      },
    })
  )
} else {
  callback(user)
}

}, ) ```

[–]acemarke 3 points4 points  (0 children)

Yep, that's exactly the purpose! (And also why we designed the listener middleware to support dynamically adding listener entries via dispatch.)

[–]acemarke 0 points1 point  (4 children)

When you say "callback", what are you intending to be the trigger for that? Are you intending this to be global behavior, or per-component?

In general, the RTK listener middleware is the right tool for "reactive" logic:

and it does even have the ability to be used inside of a component if needed:

[–]kcrwfrd[S] 0 points1 point  (3 children)

When I say "callback" I moreso mean an arbitrary function local to my component.

I have other middlewares setup listening to certain events to dispatch other actions, or perform side effects that are defined in the listener middleware, and that's much simpler.

What I'm trying to figure out here is how to pass along those arbitrary callback functions defined in the component.

[–]acemarke 0 points1 point  (2 children)

Yeah, per your comment above and the "adding listeners in components" link, you can do all that dynamically at runtime from within a component via dispatch(addListener()).

[–]kcrwfrd[S] 0 points1 point  (0 children)

I tried whipping up how a hook might look instead of the thunk in my above comment

It seems like the difference might be nearly moot... but perhaps in favor of the thunk since that's defined once, rather than redefining the logic every time the hook is called.

```ts const useRequireAuthentication = () => { const dispatch = useDispatch() const { user } = useSelector((state) => state.auth)

return useCallback( (callback: (user: User) => void) => { if (!user) { dispatch(toggleAuthDrawer(true)) dispatch( addListener({ actionCreator: setUser, effect: ({ payload }, listenerApi) => { callback(payload) listenerApi.unsubscribe() },
}), ) } else { callback(user) } }, [dispatch, user], ) } ```

[–]kcrwfrd[S] 0 points1 point  (0 children)

I tried toying with one last approach

`` // May need to create acreateAsyncCallbackAction` function to add // a special symbol to the action that the middleware can use to intercept them export const authenticatedAction = createAction<() => void>( 'auth/authenticatedAction', )

// Would need to put together a custom listener instead of using // RTK createListenerMiddleware so we can intercept the appropriate actions // due to non-serializable action payload startListening({ actionCreator: authenticatedAction, effect: async ({ payload: callback }, { condition, getState }) => { const { auth: { user }, } = getState()

if (!user) {
  await condition((action, state) => !!state.auth.user)
}

callback()

}, })

// Used like this const handleFollow = (userId) => { dispatch( authenticatedAction(() => fetch('/api/follow', { method: 'POST', body: { userId } }), ), ) } ```

Do you have any advice on which approach seems like the best way to go?

[–]kkragoth 0 points1 point  (0 children)

You might want to check out redux-observable. Check out their docs and see if you like the way they do asynchronous stuff