-
-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
replace class components (HOCs) with React Hooks
- Loading branch information
Showing
10 changed files
with
214 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { FC } from 'react'; | ||
|
||
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'; | ||
import { Button, LinearProgress, Typography } from '@material-ui/core'; | ||
|
||
const useStyles = makeStyles((theme: Theme) => | ||
createStyles({ | ||
loadingSettings: { | ||
margin: theme.spacing(0.5) | ||
}, | ||
loadingSettingsDetails: { | ||
margin: theme.spacing(4), | ||
textAlign: 'center' | ||
}, | ||
button: { | ||
marginRight: theme.spacing(2), | ||
marginTop: theme.spacing(2) | ||
} | ||
}) | ||
); | ||
|
||
interface FormLoaderProps { | ||
errorMessage?: string; | ||
loadData: () => void; | ||
} | ||
|
||
const FormLoader: FC<FormLoaderProps> = ({ errorMessage, loadData }) => { | ||
const classes = useStyles(); | ||
if (errorMessage) { | ||
return ( | ||
<div className={classes.loadingSettings}> | ||
<Typography variant="h6" className={classes.loadingSettingsDetails}> | ||
{errorMessage} | ||
</Typography> | ||
<Button | ||
variant="contained" | ||
color="secondary" | ||
className={classes.button} | ||
onClick={loadData} | ||
> | ||
Retry | ||
</Button> | ||
</div> | ||
); | ||
} | ||
return ( | ||
<div className={classes.loadingSettings}> | ||
<LinearProgress className={classes.loadingSettingsDetails} /> | ||
<Typography variant="h6" className={classes.loadingSettingsDetails}> | ||
Loading… | ||
</Typography> | ||
</div> | ||
); | ||
}; | ||
|
||
export default FormLoader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,31 @@ | ||
import { Component } from 'react'; | ||
import { FC } from 'react'; | ||
|
||
import { Features } from './types'; | ||
import { FeaturesContext } from './FeaturesContext'; | ||
import FullScreenLoading from '../components/FullScreenLoading'; | ||
import ApplicationError from '../components/ApplicationError'; | ||
import { FEATURES_ENDPOINT } from '../api'; | ||
import { useRest } from '../hooks'; | ||
|
||
interface FeaturesWrapperState { | ||
features?: Features; | ||
error?: string; | ||
} | ||
import { Features } from './types'; | ||
import { FeaturesContext } from './FeaturesContext'; | ||
|
||
class FeaturesWrapper extends Component<{}, FeaturesWrapperState> { | ||
state: FeaturesWrapperState = {}; | ||
const FeaturesWrapper: FC = ({ children }) => { | ||
const { data: features, errorMessage: error } = useRest<Features>({ | ||
endpoint: FEATURES_ENDPOINT | ||
}); | ||
|
||
componentDidMount() { | ||
this.fetchFeaturesDetails(); | ||
if (features) { | ||
return ( | ||
<FeaturesContext.Provider value={{ features }}> | ||
{children} | ||
</FeaturesContext.Provider> | ||
); | ||
} | ||
|
||
fetchFeaturesDetails = () => { | ||
fetch(FEATURES_ENDPOINT) | ||
.then((response) => { | ||
if (response.status === 200) { | ||
return response.json(); | ||
} else { | ||
throw Error('Unexpected status code: ' + response.status); | ||
} | ||
}) | ||
.then((features) => { | ||
this.setState({ features }); | ||
}) | ||
.catch((error) => { | ||
this.setState({ error: error.message }); | ||
}); | ||
}; | ||
|
||
render() { | ||
const { features, error } = this.state; | ||
if (features) { | ||
return ( | ||
<FeaturesContext.Provider | ||
value={{ | ||
features | ||
}} | ||
> | ||
{this.props.children} | ||
</FeaturesContext.Provider> | ||
); | ||
} | ||
if (error) { | ||
return <ApplicationError error={error} />; | ||
} | ||
return <FullScreenLoading />; | ||
if (error) { | ||
return <ApplicationError error={error} />; | ||
} | ||
} | ||
|
||
return <FullScreenLoading />; | ||
}; | ||
|
||
export default FeaturesWrapper; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { default as useRest } from './useRest'; | ||
export { default as useAuthorizedRest } from './useAuthorizedRest'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { redirectingAuthorizedFetch } from '../authentication'; | ||
import useRest, { RestRequestOptions } from './useRest'; | ||
|
||
const useAuthorizedRest = <D>({ | ||
endpoint | ||
}: Omit<RestRequestOptions, 'fetchFunction'>) => | ||
useRest<D>({ | ||
endpoint, | ||
fetchFunction: redirectingAuthorizedFetch | ||
}); | ||
|
||
export default useAuthorizedRest; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import { useCallback, useEffect, useState } from 'react'; | ||
import { useSnackbar } from 'notistack'; | ||
|
||
export interface RestRequestOptions { | ||
endpoint: string; | ||
fetchFunction?: typeof fetch; | ||
} | ||
|
||
const useRest = <D>({ | ||
endpoint, | ||
fetchFunction = fetch | ||
}: RestRequestOptions) => { | ||
const { enqueueSnackbar } = useSnackbar(); | ||
|
||
const [saving, setSaving] = useState<boolean>(false); | ||
const [data, setData] = useState<D>(); | ||
const [errorMessage, setErrorMessage] = useState<string>(); | ||
|
||
const handleError = useCallback( | ||
(error: any) => { | ||
const errorMessage = error.message || 'Unknown error'; | ||
enqueueSnackbar('Problem fetching: ' + errorMessage, { | ||
variant: 'error' | ||
}); | ||
setErrorMessage(errorMessage); | ||
}, | ||
[enqueueSnackbar] | ||
); | ||
|
||
const loadData = useCallback(async () => { | ||
setData(undefined); | ||
setErrorMessage(undefined); | ||
try { | ||
const response = await fetchFunction(endpoint); | ||
if (response.status !== 200) { | ||
throw Error('Invalid status code: ' + response.status); | ||
} | ||
setData(await response.json()); | ||
} catch (error) { | ||
handleError(error); | ||
} | ||
}, [handleError, fetchFunction, endpoint]); | ||
|
||
const save = useCallback( | ||
async (data: D) => { | ||
setSaving(true); | ||
setErrorMessage(undefined); | ||
try { | ||
const response = await fetchFunction(endpoint, { | ||
method: 'POST', | ||
body: JSON.stringify(data), | ||
headers: { | ||
'Content-Type': 'application/json' | ||
} | ||
}); | ||
if (response.status !== 200) { | ||
throw Error('Invalid status code: ' + response.status); | ||
} | ||
enqueueSnackbar('Update successful.', { variant: 'success' }); | ||
setData(await response.json()); | ||
} catch (error) { | ||
handleError(error); | ||
} finally { | ||
setSaving(false); | ||
} | ||
}, | ||
[enqueueSnackbar, handleError, fetchFunction, endpoint] | ||
); | ||
|
||
const saveData = () => data && save(data); | ||
|
||
useEffect(() => { | ||
loadData(); | ||
}, [loadData]); | ||
|
||
return { loadData, saveData, saving, setData, data, errorMessage } as const; | ||
}; | ||
|
||
export default useRest; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
type UpdateEntity<S> = (state: (prevState: Readonly<S>) => S) => void; | ||
|
||
export const extractEventValue = ( | ||
event: React.ChangeEvent<HTMLInputElement> | ||
) => { | ||
switch (event.target.type) { | ||
case 'number': | ||
return event.target.valueAsNumber; | ||
case 'checkbox': | ||
return event.target.checked; | ||
default: | ||
return event.target.value; | ||
} | ||
}; | ||
|
||
export const updateValue = <S>(updateEntity: UpdateEntity<S>) => ( | ||
event: React.ChangeEvent<HTMLInputElement> | ||
) => { | ||
updateEntity((prevState) => ({ | ||
...prevState, | ||
[event.target.name]: extractEventValue(event) | ||
})); | ||
}; | ||
|
||
export const updateBooleanValue = <S>(updateEntity: UpdateEntity<S>) => ( | ||
name: string, | ||
value?: boolean | ||
) => { | ||
updateEntity((prevState) => ({ | ||
...prevState, | ||
[name]: value | ||
})); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './binding'; |