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

Turbo forms with react_component not rendering React #1508

Open
uvera opened this issue Jan 20, 2023 · 4 comments
Open

Turbo forms with react_component not rendering React #1508

uvera opened this issue Jan 20, 2023 · 4 comments
Assignees

Comments

@uvera
Copy link

uvera commented Jan 20, 2023

So I'm using turbo streams for re-rendering forms when there are errors.

where I replace the form

edit.turbo_stream.erb

<%= turbo_stream.replace dom_id(@car), target: '_top' do %>
  <%= render partial: 'form' %>
<% end %>
<%= turbo_stream.replace "flashes", partial: "/flash" %>

where form
_form.html.erb

<%= form_with model: @car, id: dom_id(@car), builder: CustomFormBuilder, multipart: true, url: @car.new_record? ? admin_dashboard_cars_path : admin_dashboard_car_path(@car) do |f| %>
...
    <%= car_images_upload_input(@car) %>

    <%= signal_react_rerender %>
...

where controller actions

      def update
        @car = Car.find_by(id: params[:id])
        @car.assign_attributes(car_params)
        @car.release_date = Date.new(car_params[:release_date]&.to_i)

        if @car.save
          redirect_success
        else
          form_respond('edit')
        end
      end

      private

      def redirect_success
        redirect_to admin_dashboard_cars_path(format: :html), notice: I18n.t('flash.update.success')
      end

      def form_respond(template)
        respond_to do |format|
          format.html do
            flash[:error] = I18n.t('flash.update.error')
            render template
          end
          format.turbo_stream do
            flash.now[:error] = I18n.t('flash.update.error')
            render template
          end
        end
      end

The issue arises when I submit the form, react_component does not get re-rendered/hydrated even with

ReactOnRails.setOptions({ turbo: true });

The workaround I found is event listening for "turbo:before-stream-render"

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:load", turboReloadJs);
document.addEventListener("turbo:before-stream-render", function () {
  debouncedHandlerForNodes();
});

turboReloadJs is just for re-initializing flowbite/tailwindcss
this selector [data-signal-react-rerender] is searching for span tag from signal_react_rerender

  def signal_react_rerender
    content_tag(:span, nil, data: { signal_react_rerender: true }, class: 'hidden')
  end

Another thing

Something I noticed is without debounced and delayed call to ReactOnRails.reactOnRailsPageLoaded();
console warns with
Warning: You are calling ReactDOMClient.createRoot() on a container that has already been passed to createRoot() before. Instead, call root.render() on the existing root instead if you want to update it.

This is caused because this event gets called twice and of course, it's happening before stream rendering.

Environment

  1. Ruby version: 3.1.2
  2. Rails version: 7.0.4
  3. Webpacker version: 6.5
  4. React on Rails version: 13.2

Expected behavior

ReactOnRails should re-render/hydrate components after turbo-stream form replacement where we have react_component helper called within the replaced form

Actual behavior

Components do not get re-rendered/hydrated after turbo-stream form replacement

Small, reproducible repo

https://github.com/uvera/React-on-rails-turbo-js-bug-reproduction

@justin808
Copy link
Member

@uvera can we get a small reproducible repo?

@tomdracz any opinions of this?
CC: @ahangarha @Judahmeek

@uvera
Copy link
Author

uvera commented Apr 6, 2023

@justin808

Here it is
https://github.com/uvera/React-on-rails-turbo-js-bug-reproduction

Please check out
https://github.com/uvera/React-on-rails-turbo-js-bug-reproduction/blob/main/app/javascript/packs/application-bundle.js

and when running server http://localhost:3000/cars/new

React component does not get rendered after form submission and turbo rerender.

@justin808
Copy link
Member

@uvera can you see if #1614 fixes this issue?

@justin808
Copy link
Member

See #1620

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

3 participants