Introducing rko, a three-letter state management library for #reactjs with built-in undo, redo, and local persistence. Built on @pmndrs zustand. github.com/steveruizok/rko.
The idea here is to update state either with a "patch", or a deep partial of the state containing only the changes that you want to make...
...or else a "command" made up of two patches, before and after. Only commands become part of the undo/redo stack.
Patches are deep-merged into the previous state. In a command, the after patch is merged in right away. On undo, a command's before patch gets merged in. On redo, the after gets merged in again.
Normally, the "before" of a command just preserves the current values from the state. But you can also use it to restore earlier parts of the state, e.g. the value of a text field from before the user started editing it.
The lib is really straightforward: extend the `StateManager` class and add on methods specific to your app. (See the example for, uh, an example). Then call the methods from your app, and select out the state you need ala zustand.
The state is persisted to local storage, with some basic versioning and upgrade functionality. This is an extraction / simplification of the state I'm using for @tldraw. I'll probably go back this week and plug this in instead!
(er, not local storage, indexdb via @jaffathecake 's idb-keyval)
Just bumped with a `replaceState` method, that works like `patchState` but takes a full state instead of a patch. (This is also how the setter function of a `useState` hook works too, I guess.) Nice for moments when big fast changes are happening and deep merging would be slow.
In general though, the merges are pretty fast. The merge function I'm using is "sorta deep", meaning that it doesn't get into merging arrays or other tricky parts of a library (like deep-merge).
It's also not as defensive, so don't go merging Date objects or things like that.
The point is to avoid dropping frames while updating the state rapidly, ie while scrubbing a value or dragging lots of items.
Updating the undo/redo stack must still use commands, which involve merging patches; however, you would usually only update the undo/redo stack at the end of a rapid-update session (not during it) at which point dropping a frame wouldn't be noticeable.

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Steve Ruiz

Steve Ruiz Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @steveruizok

15 Jul
A very common #typescript pattern with some kinda tricky types behind the scenes. codesandbox.io/s/type-mapping…
Let's say we have a number of related objects (in this case, a few foods) that each have a unique type.
We can type all of them together as a union (Food), and extract their common types as a second different union (FoodType).
Read 21 tweets
30 Jun
Live cursors are interesting. You don't really want to be constantly sending updates but you do want the cursors to move smoothly and naturally like this. What's the trick?
Here's what it looks like without any animations.
Regular tweens/duration-based animations won't work here because each new update will "redirect" the animation. While the cursor is moving from A to B, a new update may come in that means it should move instead from its current point (C) to point D instead.
Read 7 tweets
29 Jun
perf breakthru on ios, panning and zooming back to 60 FPS
I was over here staring at the performance tab, all signs green, no dropped frames reported—while also watching things obviously skip around at <30 fps. Super frustrating, couldn't figure it out.
Finally I think, maybe I'm not actually updating the state on every frame? Of course I was, but somehow in a way that didn't quite count for Safari.
Read 7 tweets
27 Jun
A few updates to tldraw.com. First off, lots of perf improvements, even when lots of shapes are on the screen. Slickest SVG canvas on the web.
Slick when creating shapes, too.
I'm also handling window resize events much better. There's a slight debounce before showing shapes that had previously fallen outside of the viewport.
Read 9 tweets
18 May
Let's look at rotation in a canvas UI. Rotation is hard. 💀
When we have a single shape selected, we can start dragging on a handle here and then rotate the shape. The shape rotates around its center point.
When more than one item is selected, we do something a little different. We're actually making two changes to these shapes as we rotate the group. I'll show each change separately.
Read 12 tweets
16 May
something new
This is building on some of the patterns that I used in globs.design: a normal design canvas space and a code editor that can be used to create things on the canvas.
I've added the ability to create controls like these. A control's values may be used in the code; and when you change the control's value, the code will run again with the new value.
Read 6 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!

Follow Us on Twitter!

:(