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-5264 Create a custom hook for fetching logic on new list pages #3741

Merged
merged 13 commits into from
Jan 10, 2023

Conversation

alannadolny
Copy link
Collaborator

No description provided.

.catch(() => {
setLoading(false);
return Promise.reject(new Error(translate('react.productsList.fetch.fail.label', 'Unable to fetch products')));
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

I know you are not the author of this, but could we maybe add finally, so we setLoading(false) only once?
Apply for each hook if the same thing is there

currentParams: params,
});
})
.catch(() => Promise.reject(new Error(translate('react.stockMovement.outbound.fetching.error', 'Unable to fetch outbound movements'))));
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't see setLoading(false) if an error occurs? Consider using finally

}));

const fireFetchData = () => {
sourceRef.current = CancelToken.source();
Copy link
Collaborator

Choose a reason for hiding this comment

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

bring back the comment that was here

if (currentLocation?.id) {
sourceRef.current.cancel('Fetching canceled');
}
}, [currentLocation?.id]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you removed return from this useEffect - it was supposed to be a cleanup function (return statement inside useEffect)

Copy link
Collaborator

@drodzewicz drodzewicz left a comment

Choose a reason for hiding this comment

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

I feel like we can move quite a lot of stuff into useTable hook.
Since every TableHook has a loading state a tableData state with data, pages, totalCount and currentParams we can make it more generic and move it into useTable hook

const [loading, setLoading] = useState(true);
const [tableData, setTableData] = useState({
    data: [],
    pages: -1,
    totalCount: 0,
    currentParams: {},
});

same with fetching table data,a ll it does it fetches the data and set it in tabelData state which means we can just pass the url and params to the useTable hook like:

const url = "openboxes/api/invoice
const parmas = { ... }
const {} = useTable({ url, params })

I see that each list page has it own unique error when fetch is unsuccessful so this can also be an optional parameter that is passed to the useTable hook like an errorMessage
cc @kchelstowski

totalCount: res.data.totalCount,
pages: Math.ceil(res.data.totalCount / tableState.pageSize),
currentParams: params,
totalPrice: res.data.totalPrice,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't really like that totalPrice is defined in this hook. This is a specific data that from what I can tell is used in only one case which is Purchase Orders.
I think a solution to that could be having an optional callback onFetchedData(data) => { ... } that is passed to the useTable hook like

in useTable.jsx

        .then((res) => {
          setTableData({
            data: res.data.data,
            totalCount: res.data.totalCount,
            pages: Math.ceil(res.data.totalCount / tableState.pageSize),
            currentParams: params,
          });
         if (onFetchedData) onFetchedData(res.data)

and in usePurchaseOrderData.jsx

const [totalPrice, setTotalPrice] = useState(0);

const { ... } = useTable({ params, url, onFetchedData: (data) => setTotalPrice(data.totalPrice) })
....
return {
    ...,
    tableData: { ...tableData, totalPrice }
}

I feel like we should keep useTable hook as generic as possible and avoid having to add some single case solutions because eventually this component will grow out of control and will become messy

const url = '/openboxes/api/products';
const messageId = 'react.productsList.fetch.fail.label';
const defaultMessage = 'Unable to fetch products';
const getSortingParams = tableState => (tableState.sorted.length > 0 ?
Copy link
Collaborator

Choose a reason for hiding this comment

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

I also feel like getSortingParams can be moved to useTableData.
The logic for this seems very generic across all of the use*TableData hooks and you would only need to pass the sortColumn: 'lasUpdated' and sortOrder: 'desc' as params

import { translateWithDefaultMessage } from 'utils/Translate';

const useInboundListTableData = (filterParams) => {
const messageId = 'react.stockMovement.inbound.fetching.error';
Copy link
Collaborator

Choose a reason for hiding this comment

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

it should be named as errorMessageId

...sortingParams,
}, (value) => {
if (typeof value === 'object' && _.isEmpty(value)) return true;
return !value;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that this function's arguments should be as ( { offset, currentLocation, state, sortingParams }), because having so many arguments it might be difficult to follow the order of arguments. Making this change, you'll allow yourself not to pass them in the order that you have now.
Moreover I think that for better readability, it would be good to destructure filterParams, having:

const { receiptStatusCode, origin, destination, requestedBy, createdBy, updatedBy } = filterParams

and proceed with that, so we have:

origin: origin?.id



useEffect(() => {
if (!isShipmentStatusesFetched || shipmentStatuses.length === 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

no need for length === 0 , could be only if (shipmentStatuses.length)

pages: Math.ceil(res.data.totalCount / tableState.pageSize),
currentParams: params,
});
if (onFetchedData) onFetchedData(res.data);
Copy link
Collaborator

Choose a reason for hiding this comment

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

try onFetchedData?.(res.data) instead of having this if - if it doesn't work (but it should), at least follow the convention we have, so using brackets

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 didn't know that optional chaining works with functions. Thanks for that

@@ -14,24 +14,32 @@ import exportFileFromAPI from 'utils/file-download-util';
import { translateWithDefaultMessage } from 'utils/Translate';

const useInboundListTableData = (filterParams) => {
const messageId = 'react.stockMovement.inbound.fetching.error';
const errorMessageId = 'react.stockMovement.inbound.fetching.error';
const defaultMessage = 'Unable to fetch inbound movements';
Copy link
Collaborator

Choose a reason for hiding this comment

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

changing from messageId to errorMessageId as I requested, you should also change the defaultMessage naming to defaultErrorMessage

@@ -77,9 +81,10 @@ const useTableData = ({
pages: Math.ceil(res.data.totalCount / tableState.pageSize),
currentParams: params,
});
if (onFetchedData) onFetchedData(res.data);
// eslint-disable-next-line no-unused-expressions
Copy link
Collaborator

Choose a reason for hiding this comment

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

is that necessary?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Without this comment eslint shows that there is an unused expression

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Screenshot from 2023-01-05 10-54-34

Copy link
Collaborator

Choose a reason for hiding this comment

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

bring it back to if version then, but remember about brackets I mentioned earlier. We should avoid disabling eslint even though it is working fine. Maybe some kind of bumping up eslint even higher would help, but it's not the scope of this ticket, I just wanted to know out of curiosity if it would work so thanks for checking that

@jmiranda jmiranda merged commit 9c07e72 into develop Jan 10, 2023
@jmiranda jmiranda deleted the OBPIH-5264 branch January 10, 2023 15: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