You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If you encounter this, you may need to restructure your code in a way that avoids the circular references.
528
+
If you encounter this, you may need to restructure your code in a way that avoids the circular references. This will usually require extracting shared code to a separate common file that both modules can import and use. In this case, you might define some common action types in a separate file using `createAction`, import those action creators into each slice file, and handle them using the `extraReducers` argument.
529
529
530
-
## Managing Async Requests
530
+
The article [How to fix circular dependency issues in JS](https://medium.com/visual-development/how-to-fix-nasty-circular-dependency-issues-once-and-for-all-in-javascript-typescript-a04c987cf0de) has additional info and examples that can help with this issue.
531
+
532
+
## Asynchronous Logic and Data Fetching
533
+
534
+
### Using Middleware to Enable Async Logic
535
+
536
+
By itself, a Redux store doesn't know anything about async logic. It only knows how to synchronously dispatch actions, update the state by calling the root reducer function, and notify the UI that something has changed. Any asynchronicity has to happen outside the store.
537
+
538
+
But, what if you want to have async logic interact with the store by dispatching or checking the current store state? That's where [Redux middleware](https://redux.js.org/advanced/middleware) come in. They extend the store, and allow you to:
539
+
540
+
- Execute extra logic when any action is dispatched (such as logging the action and state)
541
+
- Pause, modify, delay, replace, or halt dispatched actions
542
+
- Write extra code that has access to `dispatch` and `getState`
543
+
- Teach `dispatch` how to accept other values besides plain action objects, such as functions and promises, by intercepting them and dispatching real action objects instead
544
+
545
+
[The most common reason to use middleware is to allow different kinds of async logic to interact with the store](https://redux.js.org/faq/actions#how-can-i-represent-side-effects-such-as-ajax-calls-why-do-we-need-things-like-action-creators-thunks-and-middleware-to-do-async-behavior). This allows you to write code that can dispatch actions and check the store state, while keeping that logic separate from your UI.
546
+
547
+
There are many kinds of async middleware for Redux, and each lets you write your logic using different syntax. The most common async middleware are:
548
+
549
+
-[`redux-thunk`](https://github.com/reduxjs/redux-thunk), which lets you write plain functions that may contain async logic directly
550
+
-[`redux-saga`](https://github.com/redux-saga/redux-saga), which uses generator functions that return descriptions of behavior so they can be executed by the middleware
551
+
-[`redux-observable`](https://github.com/redux-observable/redux-observable/), which uses the RxJS observable library to create chains of functions that process actions
552
+
553
+
[Each of these libraries has different use cases and tradeoffs](https://redux.js.org/faq/actions#what-async-middleware-should-i-use-how-do-you-decide-between-thunks-sagas-observables-or-something-else).
554
+
555
+
**We recommend [using the Redux Thunk middleware as the standard approach](https://github.com/reduxjs/redux-thunk)**, as it is sufficient for most typical use cases (such as basic AJAX data fetching). In addition, use of the `async/await` syntax in thunks makes them easier to read.
556
+
557
+
**The Redux Toolkit `configureStore` function [automatically sets up the thunk middleware by default](../api/getDefaultMiddleware.md)**, so you can immediately start writing thunks as part of your application code.
558
+
559
+
### Defining Async Logic in Slices
560
+
561
+
Redux Toolkit does not currently provide any special APIs or syntax for writing thunk functions. In particular, **they cannot be defined as part of a `createSlice()` call**. You have to write them separate from the reducer logic, exactly the same as with plain Redux code.
562
+
563
+
564
+
Thunks typically dispatch plain actions, such as `dispatch(dataLoaded(response.data))`.
565
+
566
+
Many Redux apps have structured their code using a "folder-by-type" approach. In that structure, thunk action creators are usually defined in an "actions" file, alongside the plain action creators.
567
+
568
+
Because we don't have separate "actions" files, **it makes sense to write these thunks directly in our "slice" files**. That way, they have access to the plain action creators from the slice, and it's easy to find where the thunk function lives.
569
+
570
+
A typical slice file that includes thunks would look like this:
571
+
572
+
```js
573
+
// First, define the reducer and action creators via `createSlice`
574
+
constusersSlice=createSlice({
575
+
name:'users',
576
+
initialState: {
577
+
loading:'idle',
578
+
users: []
579
+
},
580
+
reducers: {
581
+
usersLoading(state, action) {
582
+
// Use a "state machine" approach for loading state instead of booleans
583
+
if (state.loading==='idle') {
584
+
state.loading='pending'
585
+
}
586
+
},
587
+
usersReceived(state, action) {
588
+
if (state.loading==='pending') {
589
+
state.loading='idle'
590
+
state.users=action.payload
591
+
}
592
+
}
593
+
}
594
+
})
595
+
596
+
// Destructure and export the plain action creators
0 commit comments