-
Notifications
You must be signed in to change notification settings - Fork 23
Lesson 1.7
This lesson will teach you the following:
- Asynchronous Data
- Conditional Rendering
- Advanced State
- Impossible State
- Open
src/App.js
- Delete the
useSemiPersistentState
function call fromApp
- Copy the
useState
anduseEffect
hooks fromuseSemiPersistentState
function back intoApp
- Delete the
useSemiPersistentState
function - Run your application and view in browser
- Verify that your Todo List still appears correctly
Currently our list data is retrieved synchronously from the browser's storage, but in the next lesson we will be fetching it asynchronously from an API. Let's update our code to mimic asynchronous data fetching:
- Below the
todoList
state, define auseEffect
React hook with an empty dependency list - Inside the side-effect handler function, define a new Promise and pass in a callback function with parameters
resolve
andreject
- hint:
Promise()
constructor
- hint:
- To mimic a loading delay, inside the callback function declare a timeout (hint:
setTimeout
method) with the following arguments:- callback: function with no parameters
- delay time: 2000 milliseconds (2 seconds)
- Inside the timeout callback function, call the parameter
resolve
which is a callback function for when the Promise is successful and pass it an Object with propertydata
as a nested empty Object - Inside the
data
object, add a propertytodoList
and set it's value to the initial/default list state (copy fromuseState
hook) - Update the default state for
todoList
to be an empty Array - View your application in the browser
- Notice that the Todo List is now empty and doesn't persist after refresh
So what's missing? We are retrieving our list from localStorage
but we aren't updating our todoList
state with the data so it remains empty. Let's fix that:
- Chain a
then
method to yourPromise
constructor and pass it a function with parameterresult
- Inside the function, use your state setter to update the list and pass the
todoList
from yourresult
object - View your application in the browser
You'll notice now that the list is being saved in localStorage
but after refreshing the page it is reset to empty. This is because our other side-effect is overwriting the data before the asynchronous fetch is complete.
We need a way to know that the data is still loading before trying to update it in localStorage
.
- After the
todoList
state declaration, create a new state variable namedisLoading
with update function namedsetIsLoading
with default valuetrue
- Inside the second
useEffect
hook (withtodoList
dependency), add anif
statement to check thatisLoading
is false before settinglocalStorage
Now we just need to way to turn loading off once the data has been fetched.
- Revisit the
then
callback in the firstuseEffect
hook - After setting the
todoList
state, add another line to setisLoading
state tofalse
- View your application in the browser
- Enter a new todo in "Add Todo" form and submit
- Reload the page and wait 2 seconds
- Notice that the saved item now appears in the list
Great! Now our data is being saved properly again, but that delay in loading makes it seem like the list is empty at first. Let's add a loading indicator to prevent confusion.
- Inside the
App
JSX, create a new paragraph element aboveTodoList
with text "Loading..." - View your application in the browser
- Reload the page and notice that the loading message is visible
- Wait 2 seconds and notice that the Todo List appears but the loading message is still there
We don't want to always show the loading indicator, it should conditionally appear based on our isLoading
state.
- Using a ternary operator inside JSX, if
isLoading
istrue
render the loading message, otherwise render theTodoList
component - View your application in the browser
- Reload the page and notice that the loading message is visible
- Wait 2 seconds and notice that the loading indicator disappears when the Todo List becomes visible
Work in progress...