From d15f7b76fa994a02d8ddfb1e27de6924825d5499 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Mon, 27 Jan 2020 10:20:47 -0800 Subject: [PATCH] add useEndpoint hook --- .../InventoryDetail/InventoryDetail.jsx | 42 ++++++------------- .../Inventory/InventoryDetail/useEndpoint.js | 40 ++++++++++++++++++ 2 files changed, 52 insertions(+), 30 deletions(-) create mode 100644 awx/ui_next/src/screens/Inventory/InventoryDetail/useEndpoint.js diff --git a/awx/ui_next/src/screens/Inventory/InventoryDetail/InventoryDetail.jsx b/awx/ui_next/src/screens/Inventory/InventoryDetail/InventoryDetail.jsx index 3788dc130f..a9d558624c 100644 --- a/awx/ui_next/src/screens/Inventory/InventoryDetail/InventoryDetail.jsx +++ b/awx/ui_next/src/screens/Inventory/InventoryDetail/InventoryDetail.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useRef } from 'react'; +import React, { useCallback } from 'react'; import { Link, useHistory } from 'react-router-dom'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; @@ -11,37 +11,19 @@ import DeleteButton from '@components/DeleteButton'; import ContentError from '@components/ContentError'; import ContentLoading from '@components/ContentLoading'; import { InventoriesAPI } from '@api'; +import useEndpoint from './useEndpoint'; import { Inventory } from '../../../types'; function InventoryDetail({ inventory, i18n }) { - const [instanceGroups, setInstanceGroups] = useState([]); - const [hasContentLoading, setHasContentLoading] = useState(true); - const [contentError, setContentError] = useState(null); const history = useHistory(); - const isMounted = useRef(null); - useEffect(() => { - isMounted.current = true; - (async () => { - setHasContentLoading(true); - try { - const { data } = await InventoriesAPI.readInstanceGroups(inventory.id); - if (!isMounted.current) { - return; - } - setInstanceGroups(data.results); - } catch (err) { - setContentError(err); - } finally { - if (isMounted.current) { - setHasContentLoading(false); - } - } - })(); - return () => { - isMounted.current = false; - }; - }, [inventory.id]); + const { results: instanceGroups, isLoading, error } = useEndpoint( + useCallback(async () => { + const { data } = await InventoriesAPI.readInstanceGroups(inventory.id); + return data.results; + }, [inventory.id]), + inventory.id + ); const deleteInventory = async () => { await InventoriesAPI.destroy(inventory.id); @@ -53,12 +35,12 @@ function InventoryDetail({ inventory, i18n }) { user_capabilities: userCapabilities, } = inventory.summary_fields; - if (hasContentLoading) { + if (isLoading) { return ; } - if (contentError) { - return ; + if (error) { + return ; } return ( diff --git a/awx/ui_next/src/screens/Inventory/InventoryDetail/useEndpoint.js b/awx/ui_next/src/screens/Inventory/InventoryDetail/useEndpoint.js new file mode 100644 index 0000000000..9c45d7e32e --- /dev/null +++ b/awx/ui_next/src/screens/Inventory/InventoryDetail/useEndpoint.js @@ -0,0 +1,40 @@ +import { useEffect, useState, useRef } from 'react'; + +export default function useEndpoint(fetch) { + const [results, setResults] = useState([]); + const [error, setError] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const isMounted = useRef(null); + + useEffect(() => { + isMounted.current = true; + (async () => { + // Do we want this set here or not? Can result in extra + // unmounting/re-mounting of child components + setIsLoading(true); + try { + const fetchedResults = await fetch(); + if (isMounted.current) { + setResults(fetchedResults); + } + } catch (err) { + if (isMounted.current) { + setError(err); + } + } finally { + if (isMounted.current) { + setIsLoading(false); + } + } + })(); + return () => { + isMounted.current = false; + }; + }, [fetch]); + + return { + results, + isLoading, + error, + }; +}