657 Matching Annotations
  1. Oct 2020
    1. This is a very simple task for React and literally impossible for Svelte.
    2. It adds a few constructs to the language to solve one of the most complex problems in UI development — state management.
    3. The official Svelte blog, on the contrary, ends up mind tricking the reader by showing only one side of the coin, sometimes through upfront false statements about web technologies and other libs
    1. As we've briefly seen already, you can listen to any event on an element with the on: directive:
    1. A reasonably clean alternative would be to map a function over the array and use destructuring in the each loop: {#each [1, 2, 3, 4].map(n => ({ n, sqr_n: n * n })) as { n, sqr_n }} {sqr_n} {sqr_n / 2}<br> {/each}
    2. Could I get your intuition for why that rule of thumb applies to svelte components but not Javascript functions? I tend to make heavy use of let x = e when writing normal Javascript, as I do in most other languages (though unlambda is a notable exception). How is svelte different?
    1. Unlike DOM events, component events don't bubble. If you want to listen to an event on some deeply nested component, the intermediate components must forward
    1. About the argument against it, "{@const will make code less consistent ": I think the same is true now, since people can come up with very different ways of dealing with the "computed value inside each loop/if function" problem. Some extract components, some use functions, some will prepare the array differently beforehand.
    2. Do these blocks allow for reactive assignments? @lukeed They're read-only, but values update when their dependencies do
    1. Generally, you should read the value of a store by subscribing to it and using the value as it changes over time. Occasionally, you may need to retrieve the value of a store to which you're not subscribed. get allows you to do so.
    1. Sometimes, you may be tempted to write that wrapper. Because all your (React or Vue or insert your reactive framework here) instincts tell you so.Resist the temptation. There is a better way. A svelter way. Introducing: the use-directive (a.k.a. “actions”).
    2. Especially when coming from a framework like React, it might feel very tempting to start creating a component wrapper around the input (i.e. <input> becomes <Input/>) and add your custom event handlers in there.This is a great approach in React, but not so much in Svelte. Why, you ask?Well, Svelte (at least in its current form, v3) really shines when you have native DOM elements at your disposal. You can use transition directives, conditionally switch CSS classes, bind to the current value with ease, and more.
    3. However, especially when starting out, it’s very easy to fall into the “this is how I did things in my previous framework” trap.
    4. It can feel like a breeze of fresh summer air.
    1. the benchmarks that Rich chose weren't even remotely good ones. They had obvious flaws that even the authors acknowledge and Svelte's implementation actually cheats what it was testing.
    1. Svelte-routering is a great library, I think this is one of the best Routing libraries on the internet that helps us to add the routing functionality in our SPA with a minimal effort, but personally I recommend using this library if you want to create a small application with just a couple of pages and also you don't want to have all the power of a Framework. However, if you are open to use a framework, Sapper is a great option, even if you planning to create a medium size project, with Sapper you will have great control of your application.
    1. Note that interacting with these <input> elements will mutate the array. If you prefer to work with immutable data, you should avoid these bindings and use event handlers instead.
    1. const store = readable(machine.initialState, set => { service.subscribe(state => { if (state.changed) set(state) }) service.start() return () => { service.stop() } })
    2. The readable store takes a function as a second argument which has its own internal set method, allowing us to wrap any api, like Xstate or Redux that has its own built in sub­scrip­tion model but with a slightly different api.
    3. If you are wondering about the odd looking (d), this keys the component, ensuring that the compiler doesn’t do any fancy sharing of objects that leads to sur­pris­ing bugs. You don’t often need to key items in Svelte, but I have run into some cases where it is essential.
    4. Indeed, this simple contract is very close to that of an ob­serv­able, such as those provided by Rxjs. set is basically equiv­a­lent to next in the ob­serv­able world.
    5. The $ contract for auto-sub­scrib­ing is lovely in its sim­plic­ity and flex­i­bil­ity. You can adapt your own preferred state-man­age­ment pattern or library, with or without Svelte stores as helpers. Svelte does not fuss about how you want to manage your state.
    6. $: for watching de­pen­den­cies in ex­pres­sions, a much more concise useEffect, if React is familiar.
    7. Arguably what is in­ter­est­ing about Svelte’s approach to state man­age­ment is not the store itself but the auto-sub­scrip­tion that is possible because of the Svelte compiler. By simply appending a $ to a variable inside of a component, e.g. $myVariable, the compiler will know to expect an object with a subscribe method on it and generate the boil­er­plate of sub­scrib­ing and un­sub­scrib­ing for you.
  2. Sep 2020
    1. It lives in a context="module" script — see the tutorial — because it's not part of the component instance itself; instead, it runs before the component is created, allowing you to avoid flashes while data is fetched.
    1. setContext / getContext can only be used once at component init, so how do you share your API result through context? Related: how would you share those API results if the call was made outside of a Svelte component, where setContext would be even more out of the question (and the API call would arguably be better located, for separation of concerns matters)? Well, put a store in your context.
    2. Other lifecycle functions are onMount, onDestroy, etc. It is arguably less obvious that setContext is such a lifecycle method.
    3. setContext must be called synchronously during component initialization. That is, from the root of the <script> tag
    1. This is pretty good, but I don’t love that $contactStore.length bit. If we wanted to change the shape of the store from an array to a key-value store or something, we’d have to remember to update this component too. Instead, we can define a new derived store: contactCountStore. It’ll always track the count, which lets this component have less knowledge about the structure of the store. That refactor looks like this:
    2. Like with React, you can pass in callback props like onSave and onDelete, which is the main way you send data out of a component to a parent.
    3. But if you’ve spent time building front ends with components, it’s hard to go back. Svelte lets us do that with a minimum of fuss or code bloat.
    4. $: declares a relationship, where remaining should always be 10 - count. This might seem weird, but it’s conceptually the same as declaring a variable that you know will be re-calculated in every React render loop — except that remaining will get recalculated only when count changes.
    5. Since you often want to do calculations based on state, Svelte also has the “reactive declaration” symbol, $:. It’s like a let declaration, but whenever any variable referenced in the expression — count in this case — is updated, the expression is re-run, the new variable’s value is updated, and the component is re-rendered.
    6. The heart of Svelte’s magic is “reactivity”. Every let declaration sets up a listener, where any time the variable is assigned to, the change triggers a render of the component. So when the increment function calls count++, the component will re-render, which will update the value shown to the user by Count: {count}.
    1. As you can see, it uses Javascript label syntax to tell the compiler where recalculation should be carefully managed. And you thought that no one uses labels any more.
    2. The problem I have with this approach to state and prop variables is that the difference between them is very blurry. In React you can clearly see that a prop is an input to component (because of clear function notation), and that state is something internal. In Svelte they are both just variables, with the exception that props use export keyword.

      This is something I've seen before: people noticing that Svelte is missing some kind of naming convention.

      React has use___ convention, for example. Without that, it makes it hard to see the difference between and know just from the name that a function is an (mentioned in the other article I read) action and not a event handler or even component, for example.

    3. You know those useMemo and useCallback hooks? Well, Svelte has something like this. If you declare a variable like this: $: double = counter * 2;, Svelte will recalculate it only if counter changes.
    1. If you're using webpack with svelte-loader, make sure that you add "svelte" to resolve.mainFields in your webpack config. This ensures that webpack imports the uncompiled component (src/index.html) rather than the compiled version (index.mjs) — this is more efficient.
    1. It looks like the issue stems from having "svelte" as a dependency instead of a devDependencies in package.json within the sapper project. This causes import 'svelte' to load the rollup excluded npm package's set_current_component instead of from within the sapper generated server.js.
    1. Most simple example: <script> import ChildComponent from './Child.svelte'; </script> <style> .class-to-add { background-color: tomato; } </style> <ChildComponent class="class-to-add" /> ...compiles to CSS without the class-to-add declaration, as svelte currently does not recognize the class name as being used. I'd expect class-to-add is bundled with all nested style declarations class-to-add is passed to ChildComponent as class-to-add svelte-HASH This looks like a bug / missing feature to me.
    2. color: red; //doesn't apply this rule, because scoping doesn't extend to children
    3. Say I want to style this javascript routing anchor tag on various pages (some may be buttons, plain links, images) it makes it incredibly difficult. Eg:
    4. Having to wrap everything in a selector :global(child) { } is hacky
    1. I worry about that being a bit of a Pandora's box — it throws encapsulation completely out the window. The nature of CSS custom properties is that they're inert unless the child chooses to do something with them, which wouldn't be the case for other things.
    2. Allow creating custom components with the same abilities as native dom. By all means keep the same level of encapsulation, don't push class on components, but allow a component to mark the class property or another as a CSS Class property, in which case you could pass it through the same transformation that native elements go through
    3. The problem with working around the current limitations of Svelte style (:global, svelte:head, external styles or various wild card selectors) is that the API is uglier, bigger, harder to explain AND it loses one of the best features of Svelte IMO - contextual style encapsulation. I can understand that CSS classes are a bit uncontrollable, but this type of blocking will just push developers to work around it and create worse solutions.
    1. There is a good amount of properties that should mostly be applied from a parent's point of view. We're talking stuff like grid-area in grid layouts, margin and flex in flex layouts. Even properties like position and and the top/right/left/bottom following it in some cases.
    2. Svelte will not offer a generic way to support style customizing via contextual class overrides (as we'd do it in plain HTML). Instead we'll invent something new that is entirely different. If a child component is provided and does not anticipate some contextual usage scenario (style wise) you'd need to copy it or hack around that via :global hacks.
    3. The main reason using classes isn't a great solution is that it completely breaks encapsulation in a confusing way, the paren't shouldn't be dictating anything, the component itself should. The parent can pass things and the child can choose to use them or not but that is different: control is still in the hands of the component itself, not an arbitrary parent.
    4. The RFC is more appropriate because it does not allow a parent to abritrarily control anything below it, that responsibility still relies on the component itself. Just because people have been passing classes round and overriding child styles for years doesn't mean it is a good choice and isn't something we wnat to encourage.
    5. For my point of view, and I've been annoyingly consistent in this for as long as people have been asking for this feature or something like it, style encapsulation is one of the core principles of Svelte's component model and this feature fundamentally breaks that. It would be too easy for people to use this feature and it would definitely get abused removing the style safety that Svelte previously provided.
    6. This allows passing classes to child components with svelte-{hash} through the class prop and prevents removing such classes from css.
    1. The point of the feature is to not rely on the third-party author of the child component to add a prop for every action under the sun. Rather, they could just mark a recipient for actions on the component (assuming there is a viable target element), and then consumers of the library could extend the component using whatever actions they desire.
    2. They don't need to add a prop for every action. The action itself can be passed in as a prop. <script> export let action; </script> <div use:action>whatever</div> The argument for the action can be another prop or can be part of the same prop.
    1. Your tooltip component will have to wrap your image with a span tag or something, it can’t just add events to its children. And if you are adding multiple actions to it you will have to wrap it multiple times.
      <Concern1> <Concern2> </Concern2> </Concern1>

      vs.

      <img use:concern1 use:concern2>

    1. And of course, if you don't use them you don't pay for them
    2. I have created an action for form validation and its really working well
    3. the notion that any given component should be in charge of its own thing, and not do something outside of itself. I.e., loosely coupled components in a sandbox, not tightly coupled to something outside of its own scope.
    4. <slot ref:img data-visible="{{visible}}" /> In the above everything on <slot> is lost since slot is a space in the HTML, not an actual element. How could we translate this to zero or ten elements inside the slot?

      But I think this is a solved problem with current Svelte: just pass the lets to the slot content, and the slot content can decide how to pass those let props on to any or all of its child elements as it sees fit...

    5. the ability to pass around element names as strings in place of components
    1. Since one of Svelte's main principles is reacting only to data changes (as opposed to re-render the whole app with the full state all the time)
    2. I mean, it's not that bad and it's certainly not much of a runtime cost (especially since it'd only affect components which actually use it -- thanks disappearing framework!).

      "disappearing framework"

    3. Re Object.keys(undefined), I think I'm ok with that failing. AFAIK it would also fail in React
    4. The more I think about this, the more I think that maybe React already has the right solution to this particular issue, and we're tying ourselves in knots trying to avoid unnecessary re-rendering. Basically, this JSX... <Foo {...a} b={1} {...c} d={2}/> ...translates to this JS: React.createElement(Foo, _extends({}, a, { b: 1 }, c, { d: 2 })); If we did the same thing (i.e. bail out of the optimisation allowed by knowing the attribute names ahead of time), our lives would get a lot simpler, and the performance characteristics would be pretty similar in all but somewhat contrived scenarios, I think. (It'll still be faster than React, anyway!)
    1. Proving to myself that isValid does correctly change to true even when a key in $errors is an array.

    1. Child can't update things by reassignment if you do:

      <Child bind:things={things} />
      

      but can if you do;

      <Child bind:things={$object.things} />
      
    1. Demonstrates that even though object.value kind of works, it will be out of date. You need to subscribe to it to get current value: $object.value

    1. Part of the functionality that is returned are event handlers. I'd like to avoid needing to manually copy the events over one by one so the hook implementation details are hidden.
    1. Forwarding events from the native element through the wrapper element comes with a cost, so to avoid adding extra event handlers only a few are forwarded. For all elements except <br> and <hr>, on:focus, on:blur, on:keypress, and on:click are forwarded. For audio and video, on:pause and on:play are also forwarded.
    1. I'm personally surprised about that, given the degree to which web component advocates prioritise encapsulation — it seems like a footgun, honestly
    2. Personally, I think class is too blunt an instrument — it breaks encapsulation, allowing component consumers to change styles that they probably shouldn't, while also denying them a predictable interface for targeting individual styles, or setting theme properties globally
    3. ...but ultimately the component itself has control over what is exposed, and can specify its own fallback values using normal CSS custom property syntax:
    1. Proposes a syntax similar to JSX.

      My question would instead be, why not just use JSX for Svelte templates?

    2. The static analysis considerations make things like hero.enemies.map(...) a non-starter — the reason Svelte is able to beat most frameworks in benchmarks is that the compiler has a deep understanding of a component's structure, which becomes impossible when you allow constructs like that.
    1. A component should be in complete control of itself. Not only should a component's styles not leak out but other component's style should never leak in. Consider this 'Encapsulation part 2' if you will. When writing a component, you have certain guarantees that not only will the styles you write be contained within the component, but nothing from the outside should affect you either. You have a certain confidence that if it works in isolation, then it will continue to work when embedded within a complex application.
    2. CSS encapsulation is a critical feature of single file components in Svelte; it allows you to think only about the styles that live together in a given component. Managing CSS has long been one of the more challenging aspects of building for the web; we have no desire to bring those problems back via official APIs that encourage the de-scoping of CSS. We do not wish to revisit the age of namespaced CSS selectors and required preprocessors.
    3. Often, allowing the parents to compose elements to be passed into components can offer the flexibility needed to solve this problem. If a component wants to have direct control over every aspect of a component, then it should probably own the markup as well, not just the styles. Svelte's slot API makes this possible. You can still get the benefits of abstracting certain logic, markup, and styles into a component, but, the parent can take responsibility for some of that markup, including the styling, and pass it through. This is possible today.
    4. Svelte is an opinionated tool; it has opinions about how things should be done and what should be allowed. By adding constraints, we have managed to create a simple API and a performant output. These are often conscious decisions: we don't necessarily agree with historic approaches or how other tools are doing things, and we are happy to push back where we think there may be a better way. This is one of those cases, and I feel that context is important here.
    5. The problem with the export { className as class } approach is that the classes defined in the parent/calling component still have to be marked as being global otherwise they get removed.
    1. In my mind, the primary argument for this is that it's a very common thing to need and cleaner than the current alternative of string manipulation or wrapping the child component in a <div class:active><Child /></div>.
    1. Syntax-wise, I would like to be able to pass id, style and class DOM attributes as well as (ideally) svelte props to whatever the slot was replaced with, so prefixing everything with attr in the slot that should be passed sounds like a good idea. Examples: <slot attr:class=“test” attr:class:active={true} /> or <slot attr:style=“color: red” attr:id=“henlo” />
    1. So to experience another change-detector I made a little “sister” of Svelte is Malina.js, which instead of checking if a variable was changed, it checks if a binding was changed (bind-checking). Below are a few examples how it’s better.
    2. Svelte offers an immutable way — but it’s just a mask to hide “assignment”, because assignment triggers an update, but not immutability. So it’s enough to write todos=todos, after that Svelte triggers an update.
    1. To change component state and trigger a re-render, just assign to a locally declared variable.
    2. Reactive statements run immediately before the component updates, whenever the values that they depend on have changed.
    1. Svelte, on the other hand, is a compiler. In a way, Svelte is more like a programming language than a library.
    2. In most component frameworks, you need to write some code to define your component. With React, the simplest component is an empty function. In other frameworks, you need to import a library and call a special function to define and create your component. With Svelte, you just create a new .svelte file.

      If you compare these two:

      • With React, the simplest component is an empty function.
      • With Svelte, you just create a new .svelte file.

      Creating a new empty function is actually easier/faster than creating and importing a new file. Because you don't have to create a new file just to create a new one-line component. You can create simple helper components within the same file as the main component they help with, and sometimes it is nice to have the flexibility and freedom to compose your files however you want, including the freedom to group multiple closely related components together in the same file.

      In fact one thing I've sometimes found very useful and handy is to be able to define very simple helper components (functions) within the definition of my main component.

      So I would actually put this comparison in the "win" category for React, not Svelte.

    3. With Svelte, components and files have a one-to-one relationship. Every file is a component, and files can't have more than one component. This is generally a "best practice" when using most component frameworks.
    4. Being able to use an empty file as a Svelte component was useful during refactoring, because I could just create a placeholder file for the new component, import it and start using it