-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Feature request: State management through a global store. #930
Comments
I agree, it would be nice to have an Answer (with a capital A) to this question. Existing solutions are totally workable, and I think there's value in allowing people to use whatever paradigm they're already comfortable with (which I think basically boils down to Redux vs Mobx?), but it doesn't feel like it has a seal of approval. There are a couple of downsides to the current approach (subscribing to stores in lifecycle hooks):
The first problem could maybe be solved like this: import store from './store';
export default {
store,
data({ store }) {
// every time the store is updated, the component updates
// like so: `component.set(data({ store }))`
return {
foo: store.foo
};
}
}; But that design wouldn't allow you to update properties conservatively the way it currently happens. I'd be interested to hear what ideas people have for tackling this. |
I like to PR related with this issue to make global store availabe to children on some scenario, it's intended to solve problem with redux-zero. Kiho@84775b3 it also give ability to initialize state to component, today I can do only if create it with code. I made sample usage here |
Although the redux state object is new every time, the reference it holds will either be the same or not depending on whether it has changed so (as you guided not to mutate existing references)
This is an important caveat on usage that facilitates reactive UIs and something I would expect a svelte implementation to enforce on the user to use it properly. Perhaps further performance can be found by using the ideas of a memoize library like reselect Based on what 'the others are doing' I envisage that a svelte-state store should allow:
I say something along the lines of, because if there were some syntax that signalled to the compiler you were using 'svelte-state', then perhaps the user doesn't even need to do anything, the compiler would hook up the shared state into all the child components. Also since this is a 'builtin' store perhaps it need not have any external interface. Perhaps all its methods are only defined by the component methods, true also of the state shape coming only from component definitions? If the outside world wanted to dispatch an action on the state, it would have to do it through an interface of the component so perhaps components can have another property syntax similar to data() and methods() along the lines of stateData() and stateActions() and the compiler can do the magic? Of course all the above ramblings are given with a completely naive understanding of what the svelte compiler can and cant do! I don't know, just trying to dump my ideas... |
I'll throw in my two cents, since I'm one of those Rumblers 🔥 you mentioned, @ispyinternet. After a lot of rumbling, I finally went and utilized Redux-Zero, following @Kiho's helpful lead and other's advice. This is my implementation of a State Machine: https://gist.github.com/arxpoetica/fc16b1cdf3b552d761dd208d0bf5e917 If anyone has questions or wants to see more (it's not the whole yarn), I'm happy to comply. Honestly it's not perfect, but I'm so far liking the very lesser amount of boilerplate—as long as I follow the constraints I put myself under. I do like the idea of baking a store RIGHT IN Svelte itself. After having done a store, I can cite a few reasons why I think it makes sense:
One thing I learned from throwing a state machine on my app, I think it would be a mistake to have a second store built into Svelte. (I might sound like I'm contradicting myself, but I'm not.) It complicates the already existing state machine built in to Svelte. I'm not sure if this will be a popular view or not, but really I think the best thing that could happen would be to just have a really well built non-DOM-based API that allows one to wire up components at various levels—but one that doesn't easily lend itself to complicated spaghetti code. So to repeat myself, state is already baked. It just needs better tooling. So far, the solution I've been using (which is actually a non-ideal separate store) doesn't feel spaghetti. It just "connects" endpoints, which respond gracefully if components move around and are easy to plug/unplug. |
Thanks everyone for the feedback and ideas. @Kiho I like where you're going with the I've sketched out an idea for what this could look like on a gist. Would love to hear what people think! |
@Rich-Harris I am glad to hear that you liked my idea. |
@Rich-Harris I'm really on the fence about the I wonder if we do something more like I think naming convention ought to not be on the var itself, but somehow otherwise encapsulated. Alternately it could be more explicit like |
Also, there was some chatter on gitter (chitter? gatter?) regarding default state on the store. Just keeping a record of that over here too. Definitely think we need to be able to initialize the Store with some preloaded data. Common use case is to fetch JSON or whatever and populate an app while firing it up. |
Initial data works - the properties your component needs from the store are mixed in on initialisation. I get what you mean about I vote 'chitter'. |
The |
Yep, exactly: store.set({ foo: 'bar' });
store.get('foo'); // 'bar'
store.get(); // { foo: 'bar' }
// etc We'd probably want to start warning people that |
(Also, I had another thought re |
Closing this — as of 1.43 we have |
Fantastic work, @Rich-Harris. I'm still going to pick up on the So using your example from above, namely: store.set({ foo: 'bar' });
store.get('foo'); // 'bar'
store.get(); // { foo: 'bar' } What if the vars actually are named: store.set({ $foo: 'bar' });
store.get('$foo'); // 'bar'
store.get(); // { $foo: 'bar' } Does that mean templates need to reference them so??? --> <h1>Hello {{$$foo}}!</h1> Sorry not really chiming in on useful alternatives. And maybe it's an unrealistic edge case. I don't tend to throw dollar signs on vars that get used in templates, but maybe that could happen and it would really throw someone off why |
Okay, offering up an option. I think the character ought to be a non-valid js character name/identifier. So something like My vote? Btw, just so I don't sound all critical, having read all the documentation, this is some top-caliber work. I'm very excited to put it to use ASAP. |
Invalid characters are impossible because Acorn wouldn't be able to parse them — same issue as #934 (comment).
Yep! 😀 |
Okay, I'm satisfied. Thanks for letting me take a stroll. 😂 I hadn't realized you were throwing it in the JS parser. Good enough. :) Awesome work. |
as redux is to react and vuex is to vue, I really believe svelte should have its own global state / store implementation that aligns with the core philosophies and concepts of the library.
People are continually questioning these topics in gitter. Nested components demand a data down actions up solution, and the current implementation of having to manually pass data down the chain and pass events back up the chain is lacking and I feel is crying out for a baked in solution. A number of us have hacked our own implementations using redux or similar external libraries, but I feel there is room for improvement if such a solution could be architected in the core that would still align with the pre-compiled no runtime paradigm?
If I knew where to begin I would but its beyond my station.
What are the thoughts of others who understand the challenge better?
The text was updated successfully, but these errors were encountered: