5 ms·
The way I handle this, at least in React, is to create a context provider that handles my component's view state, then write my UI element as a consumer of that
by viklove 7y ago
The way I handle this, at least in React, is to create a context provider that handles my component's view state, then write my UI element as a consumer of that view state by wrapping it in an HOC. Then, if any other component wants to subscribe to the particular user interaction that drives the component I'm writing, they can simply tap into the existing context with an HOC that I've already written for them.
This way view state is kept outside of my global store, my UI component and its state controller is fully composable and extractable (meaning more reusable), and any other UI element within the same context can view and update my UI component as it pleases.
Another great thing about this is that you can scope your view state (or context) however you want. You can put it on the page level, the app level, or really wherever you want. You don't have to worry about cleaning up or resetting state because the context provider will be unmounted when the user navigates away (unlike a redux store).
- runawaybottle 7y agoCan you describe this implementation with just vanilla js? What’s the gist here, you’re using namespaced events? I’m just curious what this would look like outside of the world of React.
- viklove 7y agoThere are a lot of approaches you can take with vanilla js, but if your UI follows a component architecture that's modeled as a tree (App > Pages > Widgets), what I'm saying is that you take all of your interactive UI components and separate them into two nodes (a parent and a child). The parent P holds the state and provides callbacks to all descendants, one of which is the child C that you are writing. C is a pure component, meaning it holds no state and only invokes callbacks. You can put any number of "display" components in between P and C, but they should still be able to communicate. Now, if any components you build in the future also need access to P's state, you can easily implement it as a new pure component that is a descendant of P. Since it has access to the callbacks, it will be able to update our original component C by invoking them. With this setup, your app is basically separated into two "classes" of components, providers and consumers. Each provider holds the state and callbacks specific to itself only, which means you can easily pull out an individual provider and consumer to reuse in a new place (instead of being dependent on a global store). The biggest benefit here is that future components can interact with P and by extension C without changing any code in P or C. Furthermore, if you want two parallel widgets with independent state, you can just create two instances of P as siblings, with C as descendants of both of them. If you wanted to do the same with a global store, you would most likely have to update your implementation to support parallel state tracking. Another benefit is that you don't have to "clean up" the state when P is discarded. For example, if you are using a global store, and you navigate to a new page, you have to implement a callback to clear the widget state from the global store or risk loading stale state when the user navigates back. With this approach, since P has been removed from the tree, its state will be discarded along with it. The only stuff I put in my global store is stuff that is actually relevant to my entire application. For example the user's username and preferences.
- runawaybottle 7y agoSo my initial feeling is that it almost seems like you are reimplementing base React. Isn’t this effectively prop drilling, with a bunch of child components lifting state up to the global parent component (so that they all get updates?). Apologies if I’m simplifying it.
- viklove 7y agoWell I'm using React so I can't be re-implementing it :) I'm not advocating for any ground breaking paradigms here, I guess my only point is that the common advice to just throw everything into Redux (global store) is bad advice. You should only put global state into your global store. The common alternative is to silo state and functionality/UI into one component. I'd argue the third alternative, taking the best of both worlds, enables far more productivity. Basically creating mini-Redux stores that are only focused on one bit of user interaction. These are far more reusable, and since they're scoped locally they eliminate a lot of edge cases (and they're composable!).
- nine_k 7y agoThis sounds quite nice. I wonder if proper Redux stores could be used for that (because you can create many of them).
- deleted 7y ago[deleted]
- onion2k 7y agoContexts were added to React to replace prop drilling.
- bryanrasmussen 7y agoSince he's using the context api https://reactjs.org/docs/context.html https://reactjs.org/docs/context.html not exactly. Imagine you have a React tree with a 100 node depth. You would then need to walk all the way up those 100 nodes, but using the context api you can put in context consumer at the branches of your tree where it makes sense, so instead of walking up 100 nodes you walk up 3 nodes to input into the global context. Hope that is a reasonable high level explanation of a thing that can be complicated without experience of it.
- pgt 7y agoStore it in your DB for that user.
- username3 7y agoDo you have example code?