Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React On Rails w/Hotwire and Turbo Streams #1493

Open
braindeaf opened this issue Nov 14, 2022 · 4 comments
Open

React On Rails w/Hotwire and Turbo Streams #1493

braindeaf opened this issue Nov 14, 2022 · 4 comments
Assignees

Comments

@braindeaf
Copy link

Is there any information how to get React components to render after Turbo Stream updates? I'm got a few components which don't render when our modals update and since turbo don't have a 'after-stream-render' Event. When the modal opens I trigger ReactOnRails.reactOnRailsPageLoaded(); so that's fine but I can't work out how I can trigger this on Turbo Streams.

We are still on 11.3.0 if that makes a difference.

Many thanks :)

@justin808
Copy link
Member

Here is where the event listeners get installed.

https://github.com/shakacode/react_on_rails/blob/master/node_package/src/clientStartup.ts#L247-L278

I'm open to a PR.

Thanks,

Justin

@braindeaf
Copy link
Author

I will take a look, thank you :)

@uvera
Copy link

uvera commented Jan 20, 2023

Workaround I found (from #1508)

const debouncedHandlerForNodes = debounce(() => {
  const nodes = document.querySelectorAll("[data-signal-react-rerender]");
  if (nodes.length) {
    ReactOnRails.reactOnRailsPageLoaded();

    nodes.forEach((each) => each.remove());
  }
}, 100);

document.addEventListener("turbo:before-stream-render", function () {
  debouncedHandlerForNodes();
});

where debounce function is

function debounce(func: Function, wait: number, immediate: boolean = false) {
  let timeout;
  return function () {
    const context = this;
    const args = arguments;
    clearTimeout(timeout);
    timeout = setTimeout(function () {
      timeout = null;
      if (!immediate) func.apply(context, args);
    }, wait);
    if (immediate && !timeout) func.apply(context, args);
  };
}

You must render some div or span being hidden with data-signal-react-rerender.
Render this element as children of node you're replacing from turbo stream.

You could do this without searching for the node but you will probably get warnings.
Also you need this debounce as this event gets fired twice I think.
Without delay this won't work, rerender would not happen.

@justin808
Copy link
Member

@Judahmeek @ahangarha @uvera can the workaround go into a PR, being sure not to break existing functionality?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants