diff --git a/snippets/UseAsync.md b/snippets/UseAsync.md
deleted file mode 100644
index 8c3ac1416..000000000
--- a/snippets/UseAsync.md
+++ /dev/null
@@ -1,73 +0,0 @@
----
-title: useAsync
-tags: hooks,state,effect,intermediate
----
-
-A hook that handles asynchronous calls.
-
-- Create a custom hook that takes a handler `function` and `options`.
-- Use the `React.useState()` hook to initialize the `value`, `error` and `loading` state variables.
-- Use the `React.useEffect()` hook to call `run()` method and update the state variables accordingly if `options.autoRun` set to true.
-- Use the `run` function to manually trigger `handler` function.
-- Return an object containting the `value`, `error` and `isLoading` state variables and `run` function.
-
-```jsx
-const useAsync = (fn, options = {}) => {
- const [value, setValue] = React.useState(null);
- const [error, setError] = React.useState(null);
- const [isLoading, setIsLoading] = React.useState(false);
-
- const autoRun = options.autoRun || false;
-
- const run = async (args = null) => {
- try {
- setIsLoading(true);
- const value = await fn(args);
- setIsLoading(false);
- setError(null);
- setValue(value);
- } catch (error) {
- setIsLoading(false);
- setError(error);
- setValue(null);
- }
- };
-
- React.useEffect(() => {
- if (autoRun) {
- run();
- }
- }, [autoRun]);
-
- return {
- value,
- error,
- isLoading,
- run,
- };
-};
-```
-
-```jsx
-const App = () => {
- const handleSubmit = args => {
- // args { foo: bar }
- const url = "https://jsonplaceholder.typicode.com/todos";
- return fetch(url).then(response => response.json());
- };
-
- const submission = useAsync(handleSubmit, { autoRun: false });
-
- return (
-
-
-
{JSON.stringify(submission.value, null, 2)}
-
- );
-};
-```
diff --git a/snippets/useAsync.md b/snippets/useAsync.md
new file mode 100644
index 000000000..9881094f3
--- /dev/null
+++ b/snippets/useAsync.md
@@ -0,0 +1,65 @@
+---
+title: useAsync
+tags: hooks,state,reducer,advanced
+---
+
+A hook that handles asynchronous calls.
+
+- Create a custom hook that takes a handler function, `fn`.
+- Define a reducer function and an initial state for the custom hook's state.
+- Use the `React.useReducer()` hook to initialize the `state` variable and the `dispatch` function.
+- Define a `run` function that will run the provided callback, `fn`, while using `dispatch` to update `state` as necessary.
+- Return an object containting the the properties of `state` (`value`, `error` and `loading`) and the `run` function.
+
+```jsx
+const useAsync = (fn) => {
+ const initialState = { loading: false, error: null, value: null };
+ const stateReducer = (_, action) => {
+ switch (action.type) {
+ case 'start':
+ return { loading: true, error: null, value: null};
+ case 'finish':
+ return { loading: false, error: null, value: action.value};
+ case 'error':
+ return { loading: false, error: action.error, value: null};
+ }
+ }
+
+ const [state, dispatch] = React.useReducer(stateReducer, initialState);
+
+ const run = async (args = null) => {
+ try {
+ dispatch({ type: 'start' });
+ const value = await fn(args);
+ dispatch({ type: 'finish', value });
+ } catch (error) {
+ dispatch({ type: 'error', error });
+ }
+ };
+
+ return { ...state, run };
+};
+```
+
+```jsx
+const RandomImage = props => {
+ const imgFetch = useAsync(url => fetch(url).then(response => response.json()));
+
+ return (
+
+
+
+ { imgFetch.loading &&
Loading...
}
+ { imgFetch.error &&
Error { imgFetch.error }
}
+ { imgFetch.value &&

}
+
+ );
+};
+
+ReactDOM.render(, document.getElementById('root'));
+```