Thunk Dispatch and Handling the UI Loading State

Dispatching thunks and handing remote data loading state in a Redux toolkit application.

We'll cover the following

Introduction

In the last section, we set up a thunk. Now we get to actually integrate it into the application UI.

Consider the current click handler for the search button:

const handleSearch = async () => {
    if (searchValue) {
      setSearchValue("");
      // note that the numberOfResults is hardcoded to ten(10)
      const data = await findTweets(searchValue, 10);
      setData(data);
    }
  };

findTweets is invoked and the data received is set to the local state.

What we want to do now is dispatch the fetchTweets thunk when this button is clicked. We will also get rid of the local state set up to hold the fetched data. That’ll now be saved to the Redux store.

Let’s get started.

First we need to import the thunk:

// before 
import { findTweets } from "./findTweets";

// after 
import { fetchTweets } from "./finderSlice";

Next, we need to import useSelector and useDispatch from react-Redux.

import { useSelector, useDispatch } from "react-redux";

Now we can use these in the Finder component as follows:

// Finder.js
export function Finder() {
  ...
  const dispatch = useDispatch();
  // retrieve tweets and isLoading from the redux store 
  const { tweets, isLoading } = useSelector((state) => state.finder);
 // retrieve numberOfResults from redux store 
  const numberOfResults = useSelector((state) => state.numberOfResults);
	
  const handleSearch = async () => {
    if (searchValue) {
 	  // dispatch the thunk with state values
      dispatch(fetchTweets(searchValue, numberOfResults));
      setSearchValue("");
    }
  };

  return (
    <>
     {/* ... */}
     {/* render a loading UI, Make sure to import Stack and Skeleton from chakra-ui */}
     {isLoading && (
        <Stack mt={5}>
          <Skeleton height="20px" />
          <Skeleton height="20px" />
          <Skeleton height="20px" />
        </Stack>
      )}
      <Wrap mt={5}>
        {/* update from 'data' to 'tweets' */}
        {tweets.map((tweet) => (
          <WrapItem key={tweet.id}>
            <TweetEmbed id={tweet.id} />
          </WrapItem>
        ))}
      </Wrap>
   </>
  )
}

We should have the application working as expected with a loading indicator when the data is being fetched.

Get hands-on with 1400+ tech skills courses.