HenrikJoreteg / redux-bundler

Compose a Redux store out of smaller bundles of functionality.
https://reduxbundler.com
583 stars 46 forks source link

doFetch issue when using Redux-Bundler in React-Native #61

Open learnyst opened 4 years ago

learnyst commented 4 years ago

Hi,

We are using redux-bundler in react-native and we are facing the below issue. Please let me know what is the way to resolve these issue.

To fetch the data we are using reactor pattern. Reactor will throw a action which is a thunk function (doFetchxxx function). in doFetchxxx function we will dispatch a action to the store which will set the state as IN_PROGRESS. in reactor if the state is IN_PROGRESS we dont fetch data again

doFetchxxx is a async function. before doFetchxxx function dispatch action, if the reactor is triggered again then another doFetchxx action is thrown which will cause fetch will happen twice. We have multiple reactors in our code(> 30) and multiple will be active at a time. So always there are multiple fetch of same request.

To resolve this scenario we have added a check in doFetch function to check whether the fetch is already in_progress for that api. We will query the fetch status from the http api based on the url. This will solve the problem but it a dirty hack and we have to add this in each doFetch function.

It is better that this issue is handled in framework itself

learnyst commented 4 years ago

@HenrikJoreteg to solve this issue, i think we should not execute any reactor if there is a doFetchxx pending. Will it be possible

HenrikJoreteg commented 4 years ago

Hello! I'm not 100% sure I fully understood your question but I will do my best to answer it based on what I think you mean.

Any time a reactor returns something, the very first thing you need to do in the action creator is prevent the condition that caused the reactor to return something, otherwise you're going to have problems.

Even though thunk action creators return a function, that function will get executed synchronously. So as long as you dispatch an action that triggers a loading state, you're good. It doesn't matter how many reactors you have, it won't cause that looping state. Trust me I have pushed this very, very far 😅

However, if you make the whole action creator an async function, you're likely to have some issues. My advice is to make it a regular function that dispatches the loading state before anything async. You can still return a promise and do whatever async things you want affer, but you have to dispatch an action to set loading state first.

If you wanted to make some sort of global fetch state, you could do that but then you would end up with only allowing one asynchronous fetch at a time which means everything would have to wait for something else to finish. So if you're wanting to fetch data from several different calls as quickly as possible you'd really slow things down, because then it can't be parallelized. So I would advise against that.

However, it would be possible. You would have to create a 'extraArgs' helper that set a global fetching flag in a reducer somewhere and then every reactor would have to look for that flag. But honestly this seems like a bad idea to me for the reason described above.

learnyst commented 4 years ago

@HenrikJoreteg Thanks for reply. I will debug more based on your reply.

learnyst commented 4 years ago

Hi @HenrikJoreteg ,

In reactor-bundler, we have a function dispatchNext which trigger reactors and handle the reactor actions. In this function, dispatch is done in callback of ric.

ric will trigger callback in async way. So our actionCreater will be async and will be called when ric triggers callback.

So below are the steps which are causing issue: step-1: reactor will throw doFetch action step-2: redux-bundler will trigger doFetch in ric callback. So the doFetch will not trigger immediately and wait. step-3: if the same reactor is executed again due to some other action, since doFetch is not yet called the state of doFetch is not modified in reducer to INPROGRESS. So reactor will throw doFetch again

This will cause multiple fetch. I have verified it and the above steps are happening. We need to find a way to resolve this issue.

HenrikJoreteg commented 4 years ago

I think perhaps you're misunderstanding what's happening.

This line prevents multiple reactors functions from being triggered at the same time: https://github.com/HenrikJoreteg/redux-bundler/blob/master/src/bundles/create-reactor-bundle.js#L58

The fact that it waits before calling your action creator should be irrelevant because if it has a reactor pending shouldn't be possible for other reactors to queue up.