#Saving to database inside useEffect

1 messages · Page 1 of 1 (latest)

ebon jasper
#

I guess this is more of a React question, but I'm quite stumped as to what's going on. I'm trying to listen to input changes and save the input value to database inside a useEffect function.

But for some reason it's giving me an error of TypeError: (0 , import_note.createNote) is not a function when I'm trying to call the createNote function inside useEffect. Could someone point me to a right direction or share any insights what am I misunderstanding about how useEffect works?

I recreated the situation in a blank Indie Stack to eliminate all other sideeffects.
https://github.com/kuldar/debug-remix/blob/main/app/routes/notes/new.jsx#L10-L14

GitHub

Contribute to kuldar/debug-remix development by creating an account on GitHub.

lost monolith
#

Aha! This is in fact a Remix question. Notice that you're importing from ~/models/note.server. The Remix compiler automatically removes *.server files from the client build, and useEffect only ever runs on the client.

#

I recommend <Form>, since it's a little bit more semantic. That does mean you'll need to have a <button>Update</button> somewhere in your form for the user to click to submit it.

#

If you're dead-set on calling the action with every keystroke, which is what it appears your intention is, I would wrap it in a debounce so you don't hammer your API, and the use a fetcher. https://remix.run/docs/en/v1/hooks/use-fetcher

#

Hope that helps!

ebon jasper
#

Ahhh, thank you so much! This clears up a lot of the confusion. I got too used to writing server and client code in the same file.

The client wants a "Notion style autosave" for the textarea, so I can't use the plain old Form approach unfortunately.

I have a Tiptap editor instead of a textarea inside a form and if I understand correctly, I can't send any old data over useFetcher, but I need to have an actual form on the page with some inputs containing the value I want to post, right?

So in summary I can't just post stuff I have in useState, but I'd need to maybe have a hidden input which I pipe the content into, and then use useFetcher to submit that form, without actually reloading the page?

lost monolith
#

In your mini-example, you can wrap the <fetcher.Form> around your textarea and it will pick it up and send its value to the action. And I still highly recommend you put a debounce on it.

#

Also, you don't need <fetcher.Form> to use useFetcher

function useMarkAsRead({ articleId, userId }) {
  const marker = useFetcher();

  useSpentSomeTimeHereAndScrolledToTheBottom(() => {
    marker.submit(
      { userId },
      {
        method: "post",
        action: `/article/${articleID}/mark-as-read`,
      }
    );
  });
}

ebon jasper
#

Yes I have a debounce implemented in the actual application. It's just that the Tiptap editor is not an input field but a contenteditable, which I can't post with a Form.

lost monolith
#

Nice. Then just use fetcher.submit and shove whatever data you want in there.

ebon jasper
#

❤️ Thank you so much for helping me out! I've hit my head against the wall for better part of last 2 hours .