UI panel with React `useEffect` hook can't call `editDocument`

I’m using React in my UI panel. Contemporary React uses hooks. The concept of the useEffect hook is that,

  • actions like button clicks should set state
  • the useEffect should process ‘side effects’ that you want to happen when it observes state changes.

In my case, I have a UI panel with buttons that allow me to modify the appearance of nodes in my document. Ex. if I click a button that should increase the font size, I click it, increment the state variable fontSize in my react component. Then, useState has fontSize as a dependency which triggers its function to run. Its function calls XD’s editDocument which then has a routine to apply the new text styles to the selection. When I do this though XD gives me an error, “[Error: Panel plugin edits must be initiated from a supported UI event]” (not directly because of this asynchronous paradigm that react has). I guess there’s no way around that?

1 Like

While I’m not entirely sure about this (if someone achieved this, I’ll happily stand corrected), I believe you’re right: There isn’t a clean way around it.

In Panels, editDocument has to get called in the same tick as the user input event (or, in other words, as a direct result of an input event). As far as I understand it, useEffect gets triggered in an asynchronous fashion when the component “detects” it has to re-render. Therefore, the tick of the input event gets lost, making it impossible to use it to apply scenegraph edits.

On another note: It is only after re-reading the React docs after reading your question that I realized I should be using useEffect for a lot of things that I, until now, had handled directly in the input event handlers. Is there any real (noticeable) benefit in using useEffect for side effects (I’ve done this wrong for quite a few also larger-scale personal React projects and haven’t had any problems with it…)

As @pklaschka says, there’s no way around actually doing the editDocument() work in your actual event handler.

But I think that’s a cleaner approach anyway, rather than doing it indirectly.

1 Like