charkour / zundo

🍜 undo/redo middleware for zustand. <700 bytes
https://codesandbox.io/s/zundo-2dom9
MIT License
616 stars 20 forks source link

Resume & Pause #183

Closed RometPastak closed 2 weeks ago

RometPastak commented 3 weeks ago

I am using zustand and zundo for my input fields, but I don't want to track every change with zundo. So I thought I could do this:

<Input 
   type="number" 
   value={style.fontSize}
   onFocus={() => pause()}
   onChange={(e) => changeFontSize(e.target.valueAsNumber)}
   onBlur={(e) => {
      resume();
      changeFontSize(e.target.valueAsNumber);
   }}
/>

I am changing state on every onChange, but I am not tracking it. Pausing when input is focused and only onBlur resuming the tracking. Initial value was 50. I changed the input value to 39, with step 1. 50, 49, 48, 47... 39. You get the idea. And then I clicked outside of input, calling resume() and changing the font size one last time, so it could be tracked. Now the undo button is available to click, but by clicking it, it does not put state back to 50, but 39 instead.

So the problem is, that I want to undo back to 50, but I don't want to track every change.

RometPastak commented 3 weeks ago

I got the described situation working, by adding local useState, but I am not happy with this solution. Here is the code:

const [initialFontSize, setInitialFontSize] = useState(style.fontSize);

return (
    <Input 
       type="number" 
       value={style.fontSize}
       onFocus={(e) => {
          pause();
          setInitialFontSize(e.target.valueAsNumber);
       }}
       onChange={(e) => changeFontSize(e.target.valueAsNumber)}
       onBlur={(e) => {
          changeFontSize(initialFontSize);
          resume();
          changeFontSize(e.target.valueAsNumber);
          setInitialFontSize(e.target.valueAsNumber);
       }}
    />
);
charkour commented 2 weeks ago

Hi @RometPastak,

You'll need to call the changeFontSize function before you call pause to track the first update. Here's a Stackblitz with the update.

<Input 
   type="number" 
   value={style.fontSize}
   onFocus={() => {
      changeFontSize(style.fontSize) // Add this here!
      pause()
   }}
   onChange={(e) => changeFontSize(e.target.valueAsNumber)}
   onBlur={(e) => {
      resume();
      changeFontSize(e.target.valueAsNumber);
   }}
/>