Outputting thunk results in a component in Redux
In the last lesson, we sent a POST request using the thunk addProduct
. Now let's display the results of its work in a component.
Let's open our product app, and in it the NewProductForm.jsx
file, since this component is responsible for adding a new product. Let's look at the import lines. Let's replace the import of the productAdded
action with the import of the thunk addProduct
:
import { addProduct } from './productsSlice'
Now, since we don't track the 'pending'
request status in the slice, let's make it so that the user can click the button to save the product only once, because we don't want the same repeated requests. For this, we'll create another local state:
const [requestStatus, setRequestStatus] = useState('idle')
Next, after the handlers and before the onSaveProductClick
function, we will write code in which we will check whether all the form fields are filled in and whether the request status is in 'idle'
:
const canBeSaved =
[name, desc, price, amount, sellerId].every(Boolean) &&
requestStatus === 'idle'
Next we will change the code for onSaveProductClick
. Firstly, it will be an asynchronous function and will be executed if the above condition is true:
const onSaveProductClick = async () => {
if (canBeSaved) {}
}
Even though we don't track the 'rejected'
status in the slice, we can still print an error to the console using the try-catch
construct. We'll also add finally
here to set the local state back to 'idle'
after the request is completed:
const onSaveProductClick = async () => {
if (canBeSaved) {
try {
} catch (err) {
console.error(save product error: , err)
} finally {
setRequestStatus('idle')
}
}
}
Now that we've covered the catch
and finally
blocks, let's write some code for the try
block. Here we'll set the local state to 'in pogress'
until we get some response back from the thunk, then send our addProduct
thunk. To use the try-catch
construct depending on the type of response, we can use the RTK unwrap
function, which it adds to the returned promise. Then, if the request was successful, we set the local states to their initial states. The full code for onSaveProductClick
will look like this:
const onSaveProductClick = async () => {
if (canBeSaved) {
try {
setRequestStatus('in progress')
await dispatch(
addProduct({ name, desc, price, amount, seller: sellerId })).unwrap()
setName('')
setDesc('')
setPrice(0)
setAmount(0)
setSellerId('')
} catch (err) {
console.error('save product error: ', err)
} finally {
setRequestStatus('idle')
}
}
}
Let's run our application and try to add a new product. As you can see, in case of a successful request, the fields are cleared and a new product is added to the list of products. Also, look in the browser in Redux DevTools and run through its tabs, look at the actions and how your state changes.
Open your app with students. Open the file NewStudentForm.jsx
in it. Add another local state requestStatus
, and set it initially to 'idle'
. After reviewing the lesson materials, create a variable canBeSaved
, with the help of which the button to save new student data will work/may not work, depending on the value of request Status
and whether the fields are filled in.
Write asynchronous code for onSaveStudentClick
that will change the value of requestStatus
as needed, send a thunk addProduct
with the new student data, clear the fields in case of a successful request, and print an error to the console in case of failure, as shown in the tutorial. Use the try-catch
construct and the RTK unwrap
function for this.
Run your application, add a new student and make sure everything works.