⊗jsrxPmATTRC 55 of 57 menu

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 Statusand 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.

enru