Skip to content
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

svelte/store #951

Merged
merged 12 commits into from
Nov 25, 2017
Merged

svelte/store #951

merged 12 commits into from
Nov 25, 2017

Conversation

Rich-Harris
Copy link
Member

@Rich-Harris Rich-Harris commented Nov 24, 2017

This addresses #930 (see also this gist).

It introduces a new Store object...

import App from './App.html';
import Store from 'svelte/store.js';

const store = new Store({
  foo: bar
});

const app = new App({
  target: document.querySelector('main'),
  store
});

The store object has get, set and observe methods that work identically to those on a Svelte component, plus an onchange function that accepts a (state, changed) => void callback for handling state changes of any kind.

Store can be subclassed for adding whatever methods you need:

class MyStore extends Store {
  toggleTodo(id) {
    const { todos } = this.get();
    const todo = todos.find(todo => todo.id === id);
    todo.done = !todo.done;
    
    // you could also create a whole new todos object if you
    // care about immutability (e.g. for time travel debugging)
    // but Store doesn't care — that's up to you and your app
    this.set({ todos });
  }
}

Fairly straightforward stuff. But here comes the fun part — all children of <App> get this.store, and if you opt in with the store: true compiler option then they become bound to it.

Once bound, components can reference store properties by prefixing them with $:

<h1>Hello {{$name}}!</h1>

Store props and regular props coexist peacefully. For example a component's computed property can happily depend on both store and regular props.

Because this is Svelte, components only watch properties that they depend on, so there's no penalty for storing and updating everything centrally. The footprint is tiny (we can reuse component prototype methods, so the whole thing is less than 100 lines), and if you know how to use Svelte you already know how to use Store. And of course it's completely opt-in (we have to add component.store = component._root.options.store to the init function shared between components, but that's the only penalty for people not using Store).

I'm excited about this addition. Let me know what you all think.

TODO:

  • More tests
  • Implement bind:foo=$bar
  • Implement on:click='store.doSomething()' (i.e. whitelist store.*)

@codecov-io
Copy link

codecov-io commented Nov 24, 2017

Codecov Report

Merging #951 into master will decrease coverage by 0.01%.
The diff coverage is 92%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #951      +/-   ##
==========================================
- Coverage   91.74%   91.73%   -0.02%     
==========================================
  Files         109      109              
  Lines        4010     4051      +41     
  Branches     1287     1300      +13     
==========================================
+ Hits         3679     3716      +37     
- Misses        148      150       +2     
- Partials      183      185       +2
Impacted Files Coverage Δ
...rators/server-side-rendering/visitors/Component.ts 98.07% <100%> (+0.2%) ⬆️
src/generators/dom/index.ts 95.4% <100%> (+0.16%) ⬆️
src/generators/Generator.ts 93.87% <100%> (+0.03%) ⬆️
src/generators/server-side-rendering/index.ts 98% <100%> (+0.17%) ⬆️
src/validate/index.ts 86.66% <100%> (+0.3%) ⬆️
src/validate/html/validateEventHandler.ts 86.95% <80%> (-1.94%) ⬇️
src/generators/dom/visitors/Element/addBindings.ts 96.02% <85%> (-1.72%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 14b27b7...1cdfb84. Read the comment docs.

@Rich-Harris
Copy link
Member Author

Just to clarify — the store: true opt-in exists because reinterpreting $-prefixed properties is potentially a breaking change. I reckon it should be the default in version 2 (since it doesn't cost anything if you don't import svelte/store and don't use $-prefixed props).

@Rich-Harris Rich-Harris changed the title [WIP] svelte/store svelte/store Nov 24, 2017
@Rich-Harris
Copy link
Member Author

See #954 for another PR based on this one that adds computed properties.

@Rich-Harris Rich-Harris merged commit 1cdfb84 into master Nov 25, 2017
@Conduitry Conduitry deleted the gh-930 branch February 9, 2018 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants