To summarize, I am looking to create an epic that will make a request and dispatch an action based on whether the request is successful or not. Additionally, I want this epic to potentially dispatch more actions depending on the outcome and the current state.
The initial part is relatively simple
const fetchFooEpic: Epic<ActionAny, RootState> = (action$, store) =>
action$.pipe(
ofType<ActionAny, ReturnType<typeof actions.foo.fetch>>(actions.foo.types.FETCH_ALL),
switchMap(action =>
ajax({
method: 'GET',
url: `${path}/foo/${action.payload}`,
headers: { Authorization: store.getState().user.token }
}).pipe(
map(({response}) => actions.foo.fetchFulfilled(response)),
catchError(error => of(actions.foo.fetchRejected(error)))
)
)
)
However, I've encountered difficulties when trying to incorporate another action or an empty response. I believe mergeMap and empty should be used when nothing needs to be dispatched, but I'm receiving type errors.
const fetchMissingRelations = (response: Foo[], state: RootState) => {
const unknown: BarId[] = foo
.map(foo => foo.barId)
.filter(barId => !state.bar.entities[barId])
return unknown.length
? actions.bar.fetch([...new Set(unknown)])
: empty<never>()
}
const fetchFooEpic: Epic<ActionAny, RootState> = (action$, store) =>
action$.pipe(
ofType<ActionAny, ReturnType<typeof actions.foo.fetch>>(actions.foo.types.FETCH_ALL),
switchMap(action =>
ajax({
method: 'GET',
url: `${path}/foo/${action.payload}`,
headers: { Authorization: store.getState().user.token }
}).pipe(
mergeMap(({response}) => of(
actions.foo.fetchFulfilled(response),
fetchMissingRelations(response, store.getState())
// err: property 'type' is missing in {}
)),
catchError(error => of(actions.foo.fetchRejected(error)))
)
)
)
This issue led me to refer to https://github.com/redux-observable/redux-observable/issues/339, but explicitly specifying the never type for empty did not resolve it for me.
This is the main question (you can skip here), but here is some additional background on why I am attempting this and if anyone could offer an alternative approach:
I have several sections of data in my state that have relationships coming from different API endpoints. Specifically, I am dealing with discussions involving internal and external participants.
When fetching discussions, I aim to promptly detect any references to participants that are not yet in the state and organize requests to acquire the missing information (to display names, avatars, etc., on the UI). In scenarios where all the necessary information is already stored locally, there should be no need for further requests.
Initially, I planned to rely on connected React components to check for missing referenced entities during lifecycle events (componentDidMount/componentWillReceiveProps) and trigger actions to update the data accordingly, allowing epics to focus on their specific tasks without concerning themselves with other updates.
However, this approach has become challenging as the state data is utilized in multiple areas requiring checks and actions. While I appreciate maintaining separate state domains, I believe having discussion-related epics handle updates for other areas would result in a simpler solution. This shift would enable connected components to solely focus on rendering or awaiting data, rather than managing updates for missing references. Nevertheless, I am open to superior suggestions.