Skip to content
This repository was archived by the owner on Oct 19, 2018. It is now read-only.

Keeping Track of Multiple Components

Mitch VanDuyn edited this page Jan 13, 2017 · 8 revisions

@catmando

On the gitter.im chat I was recently asked how the following situation might be handled:

The application has several different "form" areas, that can be "opened", "edited" and then "closed." After closing the data is saved into a Store. (HyperMesh is not an option for this application for various reasons.)

Here is the problem: In addition there is "save all" button that "closes" any open forms, and persists any changes via an API. How can this "save all" button achieve this?

Here is solution pattern.

First we define a class that all of our Form's will inherit from. This class provide the capability of closing all the forms. It will simply keep track of each mounted component, and then provide a class method which will call a "close" method on each component. The subclass can define the close method in any way it needs:

class Form < React::Component::Base
  class << self
    attr_accessor :components
    def close_all
      components.each(&:close) if components
    end
  end
  before_mount do
    Form.components ||= []
    Form.components << self
  end
  before_unmount do
    Form.components.delete(self)
  end
end

Now that we have this component defined here is how we can use it:

class AForm < Form
  param :name
  def close
    if state.opened!(false)
      state.message! "I am closing..."
      after(2) { state.message! nil }
    end
  end
  render(DIV) do
    "I am #{params.name} ".span
    if state.opened
      BUTTON { 'close me' }.on(:click) { close }
    else
      BUTTON { 'open me' }.on(:click) { state.opened! true }
    end
    state.message.span if state.message
  end
end

class App < React::Component::Base
  render(DIV) do
    AForm(name: 'form 1')
    AForm(name: 'form 2')
    BUTTON { 'Close All' }.on(:click) { Form.close_all }
  end
end

This pattern might be common enough to incorporate it directly into HyperReact. See issue https://github.com/ruby-hyperloop/hyper-react/issues/159 for a similar idea.

Clone this wiki locally