Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OBPIH-4921 Improve list pages/filter component not to make unnecessar… #3526

Merged
merged 4 commits into from
Oct 10, 2022

Conversation

kchelstowski
Copy link
Collaborator

…y fetches of data (fixes after QA)

It has not been that easy straight forward as it was supposed to be, as it was not working propely on obnav and I had hard time to reproduce the issue locally, but it turned out not to be working (not always) when freshly running the project and having clean local storage. Many problems combined - the redux persist is not always working - it does not always "remember" the values - in this case it hardly ever remembers currentLocation when switching between React tabs and on the other hand if it does remember, it fetches the session data including currentLocation again, which makes the filters run again multiple times (multiple times if initially the redux persist REMEMBERED the value, so the fetch of data on list pages could continue, because currentLocation exists), but if it gets "fresh" (the same) currentLocation, it makes the fetch work again, so I had to come up with some solution to be able to "recognize" if:

  1. redux persist remembers the currentLocation
  2. To be able to determine if we initially fetched anything (so we do not fetch two times if redux persist remembered the currentLocatoin so the fetch could continue without "waiting" for another fetch of session info (FETCH_SESSION_INFO).
  3. To be able to store the previous value of currentLocation, so if it is the same as previous one, it means we don't have to fetch data again

The code, especially those if's might seem complicated, but it was the only way to prevent each of those scenarios (you can just imagine the complexity of it, if anytime you run the project again, the redux persist gave different results of either storing the session info propely or not).

I know it's not possible to fetch the session data only once when running the project if we don't have 100% React , because in the "meantime" for example our user's role might change and we should be able to refresh that data ASAP, but I think we should consider dividing the session stuff which can't change "in the meantime" without your interference (and currentLocation might be one of many), so we can avoid those complicated solutions in some places.

@jmiranda
Copy link
Member

jmiranda commented Oct 5, 2022

@awalkowiak @kchelstowski Let's discuss this on the tech huddle tomorrow.

// Avoid unnecessary re-fetches if getAppContext triggers fetching session info
// but currentLocation doesn't change
// eslint-disable-next-line max-len
if ((!initiallyFetched && currentLocation?.id) || (prevLocation && prevLocation.id !== currentLocation?.id)) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it had to be done like this because:
you might have a situation when you have currentLocation in store and you go to another list page -

  1. if we left only
if (currentLocation.id)

we would refetch twice - once having already stored location and second time when the getAppContext made a refetch.
2. if we left only

if (prevLocation.id !== currentLocation.id) 

we wouldn't make a fetch if we have currentLocation already stored, because the prevLocation would be the currentLocation (that was in store) and the currentLocation (being fetched from getAppContext) would be the same what prevLocation so we wouldn't make a single fetch.
That's why I added initiallyFetched, so if we have a situation where we have currentLocation in store, we make only one fetch, because we don't care about the currentLocation (the same) being fetched in the background from the getAppContext

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to remove the complexity if we can just get to a place where the redux hook is not invoked unnecessarily when the current location has not changed. Our suspicion is that the the app context (being a complex object) might be too complex for whatever is detecting whether the current location hsa changed. Or maybe I misread that.

Either way, one solution is adding a new API endpoint to retrieve just the current location and user IDs so that we can provide a simpler object to go through the useEffect hook to determine if the location changed.

For the issue mentioned above re: refetching twice vs not fetching at all ... I think I understand, but I have no idea how to do deal with that.

@awalkowiak mentioned that he will try to download the branch locally to test it out and see if there's an easy solution

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what I meant above is that this fix works, but I just wanted it to be understandable for your trio why I had to do it like this, because initially I also thought that it would be enough to check only prevLocation vs currentLocation but I then found some cases when it wasn't enough.
I think that separating current location from appContext would help a lot, but I do not know if it's worth including it in this ticket. We will see if @awalkowiak finds an easier solution for that.

// but currentLocation doesn't change
// eslint-disable-next-line max-len
if ((!initiallyFetched && currentLocation?.id) || (prevLocation && prevLocation.id !== currentLocation?.id)) {
if (currentLocation?.id && buyers) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had to include buyers there as well, because it could also trigger refetch (you could have currentLocation.id and fetch, but the buyers fetch was still in progress and it caused another refetch then).

@@ -170,12 +162,12 @@ const PurchaseOrderListFilters = ({
fetchStatuses();
}

if (!buyers || buyers.length === 0) {
if (!buyers) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed initialValue of buyers to null, because having it as [] was a bad idea, because if we had situation, when we would fetch none organization and made the if above like this: buyers.length > 0 we would actually never fetch if we don't have buyers' organizations (even if we don't actually need them (we don't have central purchasing enabled).

@@ -6,7 +6,7 @@ const initialState = {
data: [],
fetched: false,
suppliers: [],
buyers: [],
buyers: null,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

described above why I decided to change it

this.props.fetchMenuConfig();
TRANSLATION_PREFIXES.forEach(prefix => this.props.fetchTranslations('', prefix));
this.props.fetchSessionInfo();
this.props.initialize({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the initial load this.props.supportedLocales and this.props.locale will be empty and because you are not waiting for the data from this.props.fetchSessionInfo() you might wrongly initialize translations.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I probably forgot to change it back, as I was trying to find any possible solution for my issue. Will bring it back

return {
type: FETCH_SESSION_INFO,
payload: request,
return (dispatch) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why you refactored this action?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because it is not how redux-thunk is supposed to work - I don't understand why we were passing request in dispatch instead of payload from this request - in some cases in turned out to be understood as "fetched" when I console.logged sessionReducer, but in reality the payload didn't come yet.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kchelstowski makes sense, but then we have to refactor all remaining actions too. So I think there should be at least a TODO combined with a tech debt ticket to not forget about it.

}, [currentLocation]);
// Avoid unnecessary re-fetches if getAppContext triggers fetching session info
// but currentLocation doesn't change
// eslint-disable-next-line max-len
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it required? Looks like the next line is not that long.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to delete it after refactoring if to shorter version

}, []);
// Avoid unnecessary re-fetches if getAppContext triggers fetching session info
// but currentLocation doesn't change
// eslint-disable-next-line max-len
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

}, [props.currentLocation]);
// Avoid unnecessary re-fetches if getAppContext triggers fetching session info
// but currentLocation doesn't change
// eslint-disable-next-line max-len
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

}, [props.currentLocation]);
// Avoid unnecessary re-fetches if getAppContext triggers fetching session info
// but currentLocation doesn't change
// eslint-disable-next-line max-len
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

@@ -0,0 +1,11 @@
import { useEffect, useRef } from 'react';

export default function usePrevious(value) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is it for? Is is used anywhere?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also forgot to delete it after refactoring if. Should we consider keeping it anyway, as this hook might be useful in the future or should I delete it?

@@ -120,6 +120,7 @@ module.exports = {
templates: path.resolve(SRC, 'templates'),
store: path.resolve(SRC, 'store'),
css: path.resolve(ROOT, 'css'),
hooks: path.resolve(SRC, 'hooks'),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we using this anywhere?

@awalkowiak awalkowiak merged commit 99258ec into feature/ui-redesign Oct 10, 2022
@awalkowiak awalkowiak deleted the OBPIH-4921 branch October 10, 2022 10:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants