1

This is in continuation to the following answer: https://stackoverflow.com/a/61923286/9042295

For method 1: Fetch data before dispatch (simple), dispatch is asynchronous in my knowledge. If that's the case, is it possible to make sure that is completed before the async data fetching starts? This is to make sure that the loading text/spinner appears on time.

One method I can think of is using a useEffect hook as follows (codesandbox):

import { useEffect, useReducer } from 'react';

const initialState = {
  number: 0,
  loading: false
};

function reducer(state, action) {
  switch (action.type) {
    case 'loading': {
      return {
        number: state.number,
        loading: true
      };
    }
    case 'completed': {
      return {
        number: +action.payload,
        loading: false
      };
    }
    default:
      return state;
  }
}

// Generate random integer between 1 and 100 after 1 second delay
function genRand100() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(1 + Math.floor(Math.random() * 100));
    }, 1000);
  });
}

export default function App() {
  const [state, dispatch] = useReducer(reducer, initialState);

  // Method mentioned in earlier SO answer
  const randomizeNumber = async () => {
    dispatch({ type: 'loading' });
    const number = await genRand100();
    dispatch({ type: 'completed', payload: number });
  };

  useEffect(() => {
    if (state.loading) {
      (async () => {
        const number = await genRand100();
        dispatch({ type: 'completed', payload: number });
      })();
    }
  }, [state.loading]);

  return (
    <div
      style={{
        textAlign: 'center'
      }}>
      {state.loading ? <h1>Generating ...</h1> : <h1>{state.number}</h1>}
      <button onClick={() => dispatch({ type: 'loading' })}>
        Generate random number
      </button>
    </div>
  );
}

I want to know if this is a correct approach, or any other better ways to do this.

Aditya Verma
  • 177
  • 8

0 Answers0