Blog>
Snippets

Managing Complex State with Action Creators

Illustrate the use of action creators within custom hooks for managing complex state logic and asynchronous operations more cleanly.
const useCustomHook = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const fetchData = useCallback(async () => {
    dispatch({ type: 'FETCH_REQUEST' });
    try {
      const response = await fetch('https://api.example.com/data');
      const data = await response.json();
      dispatch({ type: 'FETCH_SUCCESS', payload: data });
    } catch (error) {
      dispatch({ type: 'FETCH_FAILURE', error });
    }
  }, [dispatch]);

  return { state, fetchData };
};
Defines a custom hook using useReducer for state management. Includes a fetchData function to handle asynchronous API calls, dispatching actions for different states of the request (request, success, failure).
const initialState = {
  loading: false,
  data: null,
  error: null
};
Initial state setup for the useReducer hook, establishing the structure for loading, data, and error states.
const reducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_REQUEST':
      return { ...state, loading: true, error: null };
    case 'FETCH_SUCCESS':
      return { ...state, loading: false, data: action.payload };
    case 'FETCH_FAILURE':
      return { ...state, loading: false, error: action.error };
    default:
      return state;
  }
};
Reducer function for handling actions dispatched by the custom hook, managing the state based on the action type.
const Component = () => {
  const { state, fetchData } = useCustomHook();

  useEffect(() => {
    fetchData();
  }, [fetchData]);

  if (state.loading) return <div>Loading...</div>;
  if (state.error) return <div>Error: {state.error.message}</div>;
  return <div>{JSON.stringify(state.data)}</div>;
};
React component example utilizing the custom hook. It fetches data on mount and renders based on the state (loading, error, data).