hyper-react icon indicating copy to clipboard operation
hyper-react copied to clipboard

`list_components_as` method

Open catmando opened this issue 9 years ago • 6 comments

Implement the following pattern

class Foo < React::Component::Base
   def self.my_components
     @my_components ||= []
   end
   before_mount { self.class.my_components << self } 
   after_mount { self.class.my_components.delete(self) }

with this macro

class Foo < React::Component::Base 
  list_components_as :my_components
end

You could of course implement a components method that works for all classes, but this way you only have the (slight) overhead when you really need it...

catmando avatar Jul 26 '16 17:07 catmando

Could you elaborate more on how this pattern is used? Also is my_components supposed to be class variable?

zetachang avatar Sep 08 '16 09:09 zetachang

pretty much says it all..

Sometimes you want to know all the components instantiated in a class.

You can do it today using before_mount/after_mount to keep track, but why not just make a method that does it.

catmando avatar Sep 09 '16 01:09 catmando

See https://github.com/ruby-hyperloop/ruby-hyperloop.io/wiki/Keeping-Track-of-Multiple-Components for a real-world use case.

catmando avatar Jan 13 '17 19:01 catmando

Perhaps a more useful way to do this is to use an "event" approach like http://notes.jetienne.com/2011/03/22/microeventjs.html

For example:

class AForm < React::Component::Base
  include MicroEvents::Receiver
  param :name
  on_event :close do
    if state.opened!(false) # keep in mind bang methods return the current state
      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) { MicroEvent.close }
  end
end

catmando avatar Jan 13 '17 21:01 catmando

I actually like this MicroEvents pattern more. It decouples the App from AForm, and makes it quite easy to handle the situation when multiple part of component tree need to trigger a close event.

zetachang avatar Jan 15 '17 09:01 zetachang

Agree... I think I will add a HyperEvent gem this week, and close this problem if it seem to fit the bill. See https://github.com/ruby-hyperloop/ruby-hyperloop.io/wiki/Keeping-Track-of-Multiple-Components (at the end) for example

catmando avatar Jan 15 '17 14:01 catmando