shakacode/react_on_rails

No node equivalent for renderStoreHydrationData

justin808 opened this issue · 3 comments

We have the ReactOnRails.render function for components.

However, if one is using a shared store and wants to do redux_store_hydration_data or redux_store, there is no equivalent JS call.

I'm probably going to skip doing this unless somebody really wants this.

  # Separate initialization of store from react_component allows multiple react_component calls to
  # use the same Redux store.
  #
  # store_name: name of the store, corresponding to your call to ReactOnRails.registerStores in your
  #             JavaScript code.
  # props: Ruby Hash or JSON string which contains the properties to pass to the redux store.
  # Options
  #    defer: false -- pass as true if you wish to render this below your component.
  def redux_store(store_name, props: {}, defer: false)
    redux_store_data = { store_name: store_name,
                         props: props }
    if defer
      @registered_stores_defer_render ||= []
      @registered_stores_defer_render << redux_store_data
      "YOU SHOULD NOT SEE THIS ON YOUR VIEW -- Uses as a code block, like <% redux_store %> "\
        "and not <%= redux store %>"
    else
      @registered_stores ||= []
      @registered_stores << redux_store_data
      result = render_redux_store_data(redux_store_data)
      prepend_render_rails_context(result)
    end
  end


  # Place this view helper (no parameters) at the end of your shared layout. This tell
  # ReactOnRails where to client render the redux store hydration data. Since we're going
  # to be setting up the stores in the controllers, we need to know where on the view to put the
  # client side rendering of this hydration data, which is a hidden div with a matching class
  # that contains a data props.
  def redux_store_hydration_data
    return if @registered_stores_defer_render.blank?
    @registered_stores_defer_render.reduce("") do |accum, redux_store_data|
      accum << render_redux_store_data(redux_store_data)
    end.html_safe
  end

And here is the JS code for render:

  /**
   * ReactOnRails.render("HelloWorldApp", {name: "Stranger"}, 'app');
   *
   * Does this:
   *   ReactDOM.render(React.createElement(HelloWorldApp, {name: "Stranger"}),
   *     document.getElementById('app'))
   *
   * @param name Name of your registered component
   * @param props Props to pass to your component
   * @param domNodeId
   * @returns {virtualDomElement} Reference to your component's backing instance
   */
  render(name, props, domNodeId) {
    const reactElement = createReactElement({ name, props, domNodeId });
    return ReactDOM.render(reactElement, document.getElementById(domNodeId));
  },

This makes no sense client-side IMO. If I want a universally shared store I can implement the entire thing in one LOC:

window.mySharedStore = mySharedStore;

Done, shared store

Is this for the case where I have a store I created using server-side rendering with ReactOnRails.registerStore({Store: Store}), and then want to use ReactOnRails.getStore('Store') for a client-side rendered component?

We (very) nearly had this use-case today, but ended up fixing the issue that was preventing us from rendering our component server-side.

@joffotron This issue is only relevant if you want to use a node server to mock out your APIs and use the same files that you use with React on Rails.