Replies: 24 comments 69 replies
-
|
I personally feel like I have one concern with the way derived values are handled either via function or memoization. import { tracked, memo } from 'ripple';
component Counter() {
let count = tracked(0);
let double = @count * 2;
<div>{@count}</div>
<div>{@double}</div>
<button onClick={() => @count++}>{"Increment"}</button>
} |
Beta Was this translation helpful? Give feedback.
-
Maybe this is a dumb question, but why is the Isn't the variable reference alone enough to tell the compiler this? |
Beta Was this translation helpful? Give feedback.
-
|
Really love it!!! It seems very intuitive and makes total sense. It's like bringing C to JS. I do have a concern about when to use Maybe I need more time to understand it, play with it and look at the compiled code. Right now everything is seamless and I don't need to use any special syntax, it's all handled behind the scenes with a But now, it will be everything like before computed automatically (or are there gotchas), plus I need to think where and how to use memo. And it's not very clear what the difference is because it seems that may not be any in certain situations. So, basically this introduces a level of unpredictability which can make people uneasy and constantly ask questions, especially given how in react people have to employ Perhaps it should always be required? Or given the architecture, things will be reactive anyway? Again, awesome idea and amazing work to get the reactivity figured out! |
Beta Was this translation helpful? Give feedback.
-
|
The @ stumped me for a second, but when you consider the cases where you do not use an @ I think it is helpful to see where you interact with a tracked value. Maybe a bit off-topic but with this in mind, do you see a way where the LSP can signal to the editor / dev that a variable / property is a Tracked (when displaying type information of stuff that is suggested by autocompletion and also values / props that are already in the code)? I like "tracked" and have no feelings about "memo". I think it is helpful to have names that are somewhat unique to effortless realise that you are looking at Ripple code. |
Beta Was this translation helpful? Give feedback.
-
|
Nice change! I wonder:
import { tracked } from 'ripple';
component Counter() {
let count = tracked(0);
let double = memo(() => @count * 2);
<button onClick={() => @double = 5}>{"Set double to 5"}</button>
<button onClick={() => @count = 2}>{"Set double to 4"}</button>
}
import { tracked } from 'ripple';
component Counter() {
let count = tracked(0);
<Child {count} />
}
component Child({ count }) {
<div>{@count}</div>
<!-- I'd say ❌ -->
<button onClick={() => @count++}>{"Increment"}</button>
}Thanks a lot! |
Beta Was this translation helpful? Give feedback.
-
|
Should we just rename |
Beta Was this translation helpful? Give feedback.
-
|
How about changing Sounds pretty good and also some developers (especially React ones) are familiar with |
Beta Was this translation helpful? Give feedback.
-
|
I have a small observations that other people might have. In my opinion, it is too verbose and adds more in the sea of frameworks. I'll recommend either go this route: tracking count = 0; Or a more symbolic approach in var name: let *count = 0; Or as function, but get rid of tracking... too verbose, too unique (not necessarily good). let count = track(0); Do not reinvent the wheel. Just use the wheel to push yourself further. |
Beta Was this translation helpful? Give feedback.
-
|
It's really great that the team is paying so much attention to early feedback, congrats! I have one question Will typescript (and thus the compiler) be aware of a variable being tracked, something like because in that case, the compiler could "know" that it's a reactive, I mean, tracked variable and thus generate the code to access or mutate the value, without the need of the '@' am I right? on the other hand, having ts recognize a Tracked variable, would allow typescript to check and enforce when we actually need a tracked variable, something like what we had with svelte 3 and Writable and a suggestion, I think it would be great if the '@' (in case we still need it) would be just syntax sugar meaning that we could write that way it would be crystal clear what the compiler is actually doing (ok perhaps the compiler is doing much more than just that...) btw, how are you currently handling nested reactivity? If I have a complex object, do I have to issue |
Beta Was this translation helpful? Give feedback.
-
|
"Just keep track of it, man." I and @WebEferen are actually heavily leaning towards:
it totally makes sense. you're telling Ripple, "hey Ripple, track this for me" and "track it by using this expression", but now "untrack this for me" it's very elegant and simple, much simpler than in other frameworks, basically it's just one word. no clunky derived or computed, useMemo, abuseMemo... The It is short to write, remember and easy on the tongue to pronounce. And this is also good for non-native English speakers as this is a pure form of a verb. "C’mon, just track it, man." |
Beta Was this translation helpful? Give feedback.
-
|
Isn’t the @ all you need? You can trace the @ back to the declaration and track it at compile time. |
Beta Was this translation helpful? Give feedback.
-
|
I like the idea, import { track, memo } from 'ripple';
component Counter() {
let count = track(0);
let double = memo(() => @count * 2);
<div>{@count}</div>
<div>{@double}</div>
<button onClick={() => @count++}>{"Increment"}</button>
}But it's a bit strange because import { track, memo } from 'ripple';
component Counter() {
let count = track(0);
let double = memo(() => count * 2);
<div>{count}</div>
<div>{double}</div>
<button onClick={() => count++}>{"Increment"}</button>
}The use of import { memo } from 'ripple';
component Counter() {
let count = 0;
let double = memo(() => @count * 2);
<div>{@count}</div>
<div>{@double}</div>
<button onClick={() => @count++}>{"Increment"}</button>
} |
Beta Was this translation helpful? Give feedback.
-
|
I’d keep |
Beta Was this translation helpful? Give feedback.
-
|
I really like this import { track, memo } from 'ripple';
component Counter() {
let count = track(0);
let double = memo(() => @count * 2);
<div>{@count}</div>
<div>{@double}</div>
<button onClick={() => @count++}>{"Increment"}</button>
}But wouldn't it be possible to omit the () => and @ in memo? It already indicates the reactive memoization, so something like: let count = track(0);
let double = memo(count * 2); |
Beta Was this translation helpful? Give feedback.
-
|
I dont get why memo exist ? |
Beta Was this translation helpful? Give feedback.
-
|
The @ when reading values is fine , but when writing values ? i think it makes sense and reads well to just assign the value without the @ appended import { tracked } from 'ripple';
component Counter() {
let count = tracked(0);
<div>{@count}</div>
<button onClick={() => count++}>{"Increment"}</button>
<button onClick={() => count = 5}>{"Set to 5"}</button>
} |
Beta Was this translation helpful? Give feedback.
-
|
Debate closed, for I have spoken: let count = track(0);
let double = memo(() => @count * 2);
effect(() => {
console.log("Count is:", @count);
console.log(untrack(() => @count));
});We can close the thread, admin! //. May I also suggest: let val = raw(count);As substitute of count.value. |
Beta Was this translation helpful? Give feedback.
-
|
Excuse me if this has been asked before. Why is tracking not opt-out, instead of opt-in? (Because you need Ripple to be a superset of TypeScript?) Imagine this: component Foo {
let count = 0
let double = count * 2
<span>Count is: {count}</span>
<Bar count={@count} />
}
Just curious if you considered this approach and what your conclusions were. Thanks! |
Beta Was this translation helpful? Give feedback.
-
|
We've had a conversation on discord on So, track / tracked / whatever can be both tracked and memo. But if you actually need to track a function swap, which is by far a much less common case, then you use a special function, maybe just So, this way, for most devs, for 98% of the time you just use one function |
Beta Was this translation helpful? Give feedback.
-
|
I noticed this code snippet that you provided: import { track } from 'ripple';
component Counter() {
let count = track(0);
<Child {count} />
}
component Child({ count }) {
<div>{@count}</div>
} Since |
Beta Was this translation helpful? Give feedback.
-
👏 very good |
Beta Was this translation helpful? Give feedback.
-
|
@trueadm what's async going to look like with this new model? |
Beta Was this translation helpful? Give feedback.
-
|
I honestly love the way this whole thing is going. however, if we use track for lets say let count = track(0); also let matched: Route | null = track(null); i might be wrong but could you help me me understand a little bit? |
Beta Was this translation helpful? Give feedback.
-
|
Thank you for all the support and ideas. We've landed on using |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
The team have been busy collecting feedback and there has been an overwhelming response that Ripple's current design towards reactivity using
$prefixed variables and properties has shortcomings:$prefixed, then they lose their charm and in reality that means they become a syntax burden. Comparisons to PHP and jQuery $ spam were common, plus it just didn't scale like I originally thought it would.$prefix has technical problems too, when working with external data incoming, having to prefix object properties to show intent feels cumbersome, not to mention incompatibility with libraries like Lexical that also make usage of$prefixing.$prefixes.$but are still reactive..ripplemodules, as the compiler can't inject the correct logic to make the$magic work – this has been a big criticism.So,
$prefixed variables were clearly a flawed design, and we've come up with a solution that we feel solves many problems and drastically simplifies the compiler output. So we're completely removing the$prefixing logic from Ripple.The new way –
tracktrack()We're removing the complicated magic that works, until it doesn't. And we're introducing something we're excited to share:
Here we create a
Trackedobject that is managed by Ripple. It doesn't expose an API for reading it, it's designed to be a black box that you know contains your state, in the casecount. It's TypeSafe and wraps your value.To access the value inside a
Trackedyou use@prefixes at the place of usage:This tells the compiler that you want to read the value inside the
Tracked.You can also mutate and update
countusing the@prefix:Furthermore, you can easily put a
Trackedinside an object to pass it around and use@inside a object property:This composes the exact same way. Which makes it really nice to pass reactivity between boundaries or used as props:
You can even create hook like functions to create and compose state:
track(fn)If you want to create a reactive function, you can just use functions:
This works just fine, but in cases where you want the reactive value to be memoized to improve performance and reduce computations, we also offer a
trackwith a function passed to it:Now
doublewill never re-compute unlesscounthas changed.As you can see it keeps to Ripple's theme of being simple and elegant. This design means we get much better type safety, inference and because we no longer need
$prefixed on props, attributes and the rest of it, it becomes far fewer things to learn. You can just assign to the component prop or DOM property like you've always done – no need for that pesky$prefix.This also means the
$childrenprop will now simply becomechildren.Why
track?We thought about using
state(), but really state is such an overloaded term. For example, if you don't want to track your variable, and you want to use aRippleArray, then that's fine – and that too is state. We're not a framework that uses signals, so we instead use tracked values – which is actually the same underlying concept that's always been there, so we're just exposing it.We also considered using
computedorderivedinstead oftrack, but we decided having a single API for reactivity was better than having a dozen of different ones.We're open to thoughts on the naming and the design. However, please let us know what you think!
Beta Was this translation helpful? Give feedback.
All reactions