-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider adding types and logic for handling normalized state #333
Comments
https://resthooks.io/docs/guides/redux looks interesting. |
Ultimately, what I'm thinking here is:
|
As an initial exploratory step, I spent some time today trying to port The first step was trivial: I copied the code, and replaced the couple Angular-specific imports with I then started reworking the "state adapter" logic to use Immer instead. This allowed me to simplify it considerably. The outer wrapping layer always made preemptive copies of By using Immer both at the wrapping layer and internally, I was able to delete all references to the I haven't actually figured out where I'm going with this process overall, or actually tried using this entity logic in any kind of an app. I'm just poking around at it to get an idea of what it does and how we might be able to use (and reuse) it. I've pushed up my changes as a |
This evening's experimentation:
I did run into some weird behavior with Immer, where nested That of course wouldn't be an issue if I hadn't just gone in and Immer-ified the guts of the entity logic. Other than that Immer issue, I really like where this is going. Problem is, I've just forked the original Current code is here: Huh. One other note. Looks like the branch fails CI checks against TS 3.3 for some reason. |
Hey! Would be amazing to have something "officially" supported for such a common use case! I did build something a while ago that was heavily inspired by the AngularJS 1.0 At the time I tried to make things as simple as possible, so there is many things that could be improved (store layout, actual API, etc.) and except a recent rewrite to TypeScript for fun, the code is quite old! If you wanna have a quick look: redux-rest-resource, docs. A few things that I do personally look for: To have a very straightforward API, eg. import {actions as usersActions} from 'src/store/modules/users';
const UserList: FunctionComponent<Props> = () => {
const {fetchUsers, deleteUser} = useActions(usersActions, []);
const users = useSelector<State, User[]>(state => state.users.items);
[...]
} const {actions, rootReducer} = createResource({
name: 'user',
url: `${HOST_API_URL}/users/:_sid`,
credentials: 'include'
});
export {actions};
export default rootReducer; To be able to easily combine sub-resources (eg. To be able to define custom actions: const missionResource = createResource({
name: 'mission',
url: `${HOST_API_URL}/missions/:_sid`,
credentials: 'include',
actions: {
publish: {method: 'POST', gerundName: 'publishing', url: './publish'},
schedule: {method: 'POST', gerundName: 'scheduling', url: './schedule'},
cancel: {method: 'POST', gerundName: 'cancelling', url: './cancel'},
update: {
assignResponse: true
}
}
}); Another project that you might want to check: Redux Resource that took another very different approach on API and store layout. @ngrx/data does look pretty interesting, I might be interested to contribute / beta test something like this! Looking forward to following your thoughts on this subject! |
@mgcrea : thanks for the feedback! I remember running across your lib at some point, and know I have it included in the list of entity management addons I linked up in the top comment. I'll agree that higher-level abstractions are valuable. But, for now, I'm trying to avoid having RTK do any of the actual fetching work. That's why I'd started to look at |
@markerikson Any thoughts on adding multiple "indexes" to the normalized state created by createEntityAdapter? For example, right now it provides data organized around ids. You can customize the selector to use whatever field you like, but it's a single field. For comparison, I have a project where my normalization groups the code into both a "byId" and "byName" collections, and I can access it both ways. Not sure such a thing is possible with the current setup short of duplicating the data into another slice. |
One problem is the query of items vs single item issue. I.e. how do you make sure your data is not stale when you are editing one user in a list of users or you have deleted one user from your store. Often you might have used a query to have some serverside filtering before you fetched your objects - say GET /api/users?type=employees&orderBy=name&page=1&pageSize=20 Thus you rely on the ordering and membership info of that query when displaying the objects and you need a way to remember to reload or invalidate the querydata when you edit the underlying objects. Also there is the problem of caching. I would love to be able to have a n tied system like this:
Where I have good methods for invalidating the SW from both sides and where the store system handles stale while invalidate variants so I can do a query, show the user the result from the service worker, but let the serviceworker send an update to redux when the new result is ready. One last thing, there should be a way for non CRUD requests to float through the same system - f.x. a batch update of item scores. |
@tarjei : that goes off into the question of cache management, which is not a problem I'm trying to solve. The goal of this issue is simply to provide the reducer logic for doing the state updates. Where and how you make use of that reducer logic is up to you. @DWMiller : that's an interesting idea, and worth exploring at some point. Probably not something I'm worried about for the initial release, though. |
Just released https://github.com/reduxjs/redux-toolkit/releases/tag/v1.3.0-beta.0 , which has a (hopefully) stable and documented version of |
v1.3.0 with That resolves this issue. |
Given that we recommend normalizing state, it would be nice to have at least some amount of built-in tooling to help with that. This was also on Dan's wishlist of things to include in a Redux addon layer:
I previously asked on Twitter about the idea of adding something like this:
https://twitter.com/acemarke/status/1216766299688316928
The NgRX platform has a library called
@ngrx/entity
( https://ngrx.io/guide/entity ), which contains some type definitions and helpers for working with normalized state. Per discussion with an NgRX dev, that library is already almost completely framework-agnostic - it just has a couple NgRX/Angular-specific imports.I just opened up ngrx/platform#2333 to ask if they might be able to tweak it and make it truly agnostic, in which case we might be able to depend on
@ngrx/entity
ourselves.Alternately, we could copy-paste the code with attribution.
There's also a bunch of other libraries for dealing with entity management, which I have listed at https://github.com/markerikson/redux-ecosystem-links/blob/master/entity-collection-management.md .
Key considerations:
createSlice
to generate entity actions and reducers or something, but we've already seen that can get tricky in TypeScriptThe text was updated successfully, but these errors were encountered: