Hacker News new | past | comments | ask | show | jobs | submit login

I think the biggest problem is the default approach of using thunks for handling async state. You get these "opinionated" frameworks that then reinforce terrible design ideas.

If it's simple just put handle async stuff in situ. If it's more complex, use custom middleware. Thunks, sagas, etc are all anti-patterns. The single worst thing the Redux docs did was give the impression that middleware was some kind of advanced functionality only useful for library designers. Most of your app logic should probably live in middleware.

The "redux toolkit" or whatever doesn't help with that, it only reifies questionable practices. Skip it. Write a simple utility for generating actions/types, and then go about your business.




I'll have to disagree with that, on multiple levels.

Thunks are simply an approach for writing reusable async logic that has access to `dispatch` and `getState`, without being tied to a specific store [0]. While I do think more people would benefit from writing middleware for their own particular use cases, most people just want to have a place where they can fetch some data and dispatch an action containing the result. Thunks make that straightforward. Thunks are also by far the most widely used async middleware across the Redux ecosystem. These are all reasons why we settled on thunks as the default async middleware included in RTK [1]. (It is worth noting that with the advent of `useDispatch` and hooks, you can write some fetching logic directly in a `useEffect` call vs a thunk, but there's still benefits to using thunks in many cases.)

RTK has specific support for thunks in two ways. `configureStore` automatically adds the thunk middleware to the store setup [2], and we have a `createAsyncThunk` API [3] that handles the common pattern of dispatching actions based on the results of a promise.

However, nothing about that requires that you use thunks with RTK. You can still add whatever middleware you want to the store, whether it be sagas, observables, custom middleware, or something else.

> The "redux toolkit" or whatever doesn't help with that, it only reifies questionable practices. Skip it. Write a simple utility for generating actions/types, and then go about your business.

I'm afraid this is entirely wrong.

RTK encodes the best practices recommended in our Style Guide docs page [4], and includes APIs that simplify your Redux logic considerably:

RTK improves your Redux code in many ways:

- `configureStore` lets you set up a Redux store in one line with good defaults built in, including automatically adding the Redux-Thunk middleware, enabling the Redux DevTools Extension, and warning about accidental mutations

- `createSlice` generates action creators and action types for you automatically - all you have to do is write reducers and given them reasonably descriptive names. In addition, it uses Immer internally to let you write "mutating" reducer logic that is safely turned into correct immutable updates, so no more nested spread operators.

- As mentioned, `createAsyncThunk` handles the typical use case of dispatching actions before and after making an async request - just fetch your data and return a promise, and it'll dispatch actions automatically.

- `createEntityAdapter` provides prebuilt reducer logic for typical collection management operations, like `upsertMany`, `addOne`, `removeAll`, etc.

So, RTK _is_ that "simple utility for generating actions", and more. It's an official package from the Redux team (ie, myself and the other maintainers), you can pick and choose which of its APIs you actually use in your app, and you can mix and match which parts of your Redux logic are written with RTK with parts that might still be written with other approaches.

[0] https://blog.isquaredsoftware.com/presentations/workshops/re...

[1] https://blog.isquaredsoftware.com/2020/02/blogged-answers-wh...

[2] https://redux-toolkit.js.org/api/configureStore

[3] https://redux-toolkit.js.org/api/createAsyncThunk

[4] https://redux.js.org/style-guide/style-guide


What's with the copy paste spam on every one of your posts?

None of what you're saying matters in the scheme of things. You can get everything you need from

    const { types, actions } = createActions([ 'ACTION_NAME', ...]);
Where createActions is an exercise for the reader, but shouldn't take more than a few lines. Then go about your business from there. Adding another layer of framework over the top of this stuff only obscures what's going on under the covers.

The middleware approach is more straightforward than thunks and far more maintainable. Reifying that as "best practice" is only going to continue to spread this anti-pattern because no real application is about "just grabbing some data for a bit" and inevitably that one api call expands into many, not to mention all of the other side effect related and asynchronous functionality that one has to deal with in user interfaces.


He's been doing it for a while now. I believe he has setup some google alerts on the words 'redux | thunks | sagas' and he just brings his redux toolkit gospel along. And not just on this site, like, everywhere. Dev.to, reddit, twitter...

I've confronted him once but to no avail, I even got downvoted by the community. :)

https://www.reddit.com/r/reactjs/comments/fvuwpl/handling_si...

edit: i see that's happening to you too here lol, godspeed


They are one of the maintainers of Redux Toolkit (which has made Redux so much nicer to work with)


Honestly, the only alert I have is a Tweetdeck search for hashtag `#redux`.

Other than that, I just spend too much time on social media :)


I would shorten the copy to be more effective.


Haha yeah. Evangelists, man. Ah well, what can you do.


Or, with `createSlice`, you get the action creators for free with your reducers:

    const todosSlice = createSlice({
      name: 'todos',
      initialState: [],
      reducers: {
        addTodo(state, action) {
          const { id, text } = action.payload
          state.push({ id, text, completed: false })
        },
        toggleTodo(state, action) {
          const todo = state.find(todo => todo.id === action.payload)
          if (todo) {
            todo.completed = !todo.completed
          }
        }
      }
    })

    export const { addTodo, toggleTodo } = todosSlice.actions

    export default todosSlice.reducer
You're welcome to your own opinion, but we've designed RTK based on how we've seen the community use Redux, and built it to solve the problems they're dealing with.


I see what you’re doing there. I also see why you think it’s a good idea. "How the community" uses redux is badly. I guess congrats for reinforcing that at scale. Gives me some more hours to bill when I run across the next ratsnest.


Can you provide some examples of a better way to use redux? The react and redux toolchain is so flexible I'm always interested to see what ways other people come up with to use it.


I have a copy paste dump that I did a few months back to show someone how I was working, happy to pass that along. I wouldn't make claims that the way I'm using things are the best but so far I've been happy with the general approach. There's a simple createActions and a more complex one that handles namespacing.

https://gist.github.com/weeksie/04f41329d0015e2128209df9f9de...

I skimmed the debounce middleware from this guy Nir Kaufman who has some pretty good things to say about front end architecture. Generally with Redux we have a system that can absolutely provide real event-driven CQRS style front end so it seems crazy to ignore that in favor of managing async thunks like it's 2004 and we've all just discovered how to put an XMLHTTPRequest on an onclick handler or something.

Outside of that core.effects file, I put all of the async app logic in custom middleware as well. YMMV but using a framework for replacing const declarations and switch statements is overkill.

The broader point is that if you're going to create utilities like that, it's often worth just rolling your own. When you attach a core part of your application to a framework you've signed up for the ride. I realize it seems like I'm being an asshole to acemarke, who appears to be a perfectly lovely dude, if a little passive-aggressive, but I sincerely feel like pushing libraries for problems that shouldn't require libraries is making our ecosystem worse.




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: