3 ms·
Yeah, for a while it seemed like there was a new Redux side effects lib coming out every week. At this point, though, it's pretty much standardized on thunks f
by acemarke 8y ago
Yeah, for a while it seemed like there was a new Redux side effects lib coming out every week. At this point, though, it's pretty much standardized on thunks for basic use cases, and either sagas or observables for more advanced use cases based on your preference of writing async logic.
> What I've taken to doing is exporting a dispatch function that calls the store's dispatch, not the store.
Not sure I follow that train of thought - could you point to an example?
> Actions themselves make perfect sense from the perspective of a reducer, and clearly they must be dispatched, but they're a state management detail that the UI doesn't need to know about. Something similar to redux-action could be the default.
This is why we recommend use of action creators, so that a component is just calling `this.props.doSomething()` without it "knowing" that a Redux action is actually being dispatched.
Per your snippet there at the end:
- `redux` and `react-redux` are deliberately separate packages, because the Redux core is 100% vanilla JS, and independent from React (in the same way that `react` and `react-dom` are separate packages - the core React logic is independent of the platform-specific reconcilers). So, `import {connect} from "redux"` wouldn't be appropriate.
- The use of `deleteFoo()` that way assumes that it's pre-bound to a specific store instance, which limits the reusability of your logic, and also makes it a lot harder to test. `connect` abstracts away the question of "which store instance am I interacting with?", so that your components and logic are more testable and reusable.
> Something similar to redux-action could be the default.
For what it's worth, earlier this year I threw together a small `redux-starter-kit` package: https://github.com/markerikson/redux-starter-kit https://github.com/markerikson/redux-starter-kit . The goal behind it is to simplify some of the most common pain points around Redux: store setup (including thunks and devtools), writing immutable updates in reducers, and having to install multiple packages out of the box. The biggest thing I know it's still missing at this point is indeed something akin to `redux-actions` - see my notes at https://github.com/markerikson/redux-starter-kit/issues/17 https://github.com/markerikson/redux-starter-kit/issues/17 .
I haven't had time to push it forward further, but I would seriously like to get some more eyes on it, see if there's any other use cases we should be covering, and then make it an official Redux-branded package and update our docs to recommend that people use it.
- strken 8y ago> Not sure I follow that train of thought - could you point to an example? Something like const store = createStore(...) export const dispatch = (action) => store.dispatch(action) It removes the temptation to read directly from the store. > `redux` and `react-redux` are deliberately separate packages Yeah, my bad, got the import wrong. > ...limits the reusability of your logic... When would this become a problem, in practice? Reusable actions across different react/react-native UI, or multiple apps? Switching between user accounts? How common a use case is it? Even if this is a constraint, I'm of two minds about whether a hack in isolation is worse than more complicated action boilerplate in general. > ...and also makes it a lot harder to test... This can be mitigated by Jest's mocks. > https://github.com/markerikson/redux-starter-kit https://github.com/markerikson/redux-starter-kit That's really good. Unfortunately, it's not the same thing as bundling it with Redux proper. Anyway, thanks for engaging with me. I never intended to do a deep dive into Redux's design, only to sympathise with stupidcar's comments about third-party state management, but it's interesting to hear the perspective of a maintainer.
- acemarke 8y agoSure. I'll toss in a few more thoughts here in response. Your `dispatch` snippet could be simplified to just `const {dispatch} = store`, because the store isn't a class instance - it's a closure. However, I'm not sure why you'd feel a need to "remove the temptation to read directly from the store". In what scenario are you trying to dispatch actions (presumably from the UI), but not read any data? A basic example of reusability is the unit testing scenario itself. Ideally, you want to minimize the amount of other app code that's getting pulled in, so you can test this one piece in isolation. A React component shouldn't "know" about a store at all - it should just be getting data and functions as props. Similarly, even async logic _should_ be testable in reasonable isolation. If you are directly importing a singleton store instance throughout the entire app, you're coupling all of your logic to that one instance. Typical testing of store-related logic involves the `redux-mock-store` package, which is just similar enough to a real store to let code run, but records which actions have been dispatched. Similarly, if you do want to test a Redux-connected component and its pieces all together, you would normally provide a unique store or mock store instance there in the unit test - you don't want to drag in the rest of your codebase to test that one piece. (And sure, Jest has some pretty good mocking abilities, but not everyone's using Jest.) I've got some slides on standard Redux unit testing practices [0], and a large section on testing in my React/Redux links list [1]. Outside of testing, yes, reuse of React+Redux across multiple platforms is viable, as is sharing code in libraries. But, again, that only works if the store is effectively dependency-injected at runtime, and that's the point of how things like `connect()`, thunks, and sagas are set up. I agree that a separate "starter" package isn't the same as putting that all in the core, but that's kind of the point. The starter kit depends on several other packages (`redux-thunk`, `immer`, `selectorator`, etc), while the core Redux library is tiny and standalone. The intent has always been to keep the core small, and let people build pieces on top of it. So, for this package, the specific goal is to help simplify the most common use cases and concerns I've seen, while still avoiding dictating the rest of their app design. [0] https://blog.isquaredsoftware.com/presentations/workshops/redux-fundamentals/unit-testing.html https://blog.isquaredsoftware.com/presentations/workshops/re... [1] https://github.com/markerikson/react-redux-links/blob/master/react-redux-testing.md https://github.com/markerikson/react-redux-links/blob/master...