| id | component-api |
|---|---|
| title | Component API |
| permalink | component-api.html |
| prev | top-level-api.html |
| next | component-specs.html |
Reactrb Components are ruby classes that either subclass React::Component::Base, or mixin React::Component. Both mechanisms have the same effect.
Instances of React Components are created internally by React when rendering. The instances exist through subsequent renders, and although coupled to React, act like normal ruby instances. The only way to get a valid reference to a React Component instance outside of React is by storing the return value of React.render. Inside other Components, you may use refs to achieve the same result.
A component may define callbacks for each phase of the components lifecycle:
before_mountrenderafter_mountbefore_receive_propsbefore_updateafter_updatebefore_unmount
All the callback macros may take a block or the name of an instance method to be called.
class AComponent < React::Component::Base
before_mount do
# initialize stuff here
end
before_unmount :cleanup # call the cleanup method before unmounting
...
endExcept for the render callback, multiple callbacks may be defined for each lifecycle phase, and will be executed in the order defined, and from most deeply nested subclass outwards.
Details on the component lifecycle is described here
Within a React Component the param macro is used to define the parameter signature of the component. You can think of params as
the values that would normally be sent to the instance's initialize method, but with the difference that a React Component gets new parameters when it is rerendered.
The param macro has the following syntax:
param symbol, ...options... # or
param symbol => default_value, ...options...Available options are :default_value => ...any value... and :type => ...class_spec...
where class_spec is either a class name, or [] (shorthand for Array), or [ClassName] (meaning array of ClassName.)
Note that the default value can be specied either as the hash value of the symbol, or explicitly using the :default_value key.
Examples:
param :foo # declares that we must be provided with a parameter foo when the component is instantiated or re-rerendered.
param :foo => "some default" # declares that foo is optional, and if not present the value "some default" will be used.
param foo: "some default" # same as above using ruby 1.9 JSON style syntax
param :foo, default: "some default" # same as above but uses explicit default key
param :foo, type: String # foo is required and must be of type String
param :foo, type: [String] # foo is required and must be an array of Strings
param foo: [], type: [String] # foo must be an array of strings, and has a default value of the empty array.The component instance method params gives access to all declared params. So for example
class Hello < React::Component::Base
param visitor: "World", type: String
render
"Hello #{params.visitor}"
end
endA param of type proc (i.e. param :update, type: Proc) gets special treatment that will directly
call the proc when the param is accessed.
class Alarm < React::Component::Base
param :at, type: Time
param :notify, type: Proc
after_mount do
@clock = every(1) do
if Time.now > params.at
params.notify
@clock.stop
end
force_update!
end
end
def render
"#{Time.now}"
end
endIf for whatever reason you need to get the actual proc instead of calling it use params.method(*symbol name of method*)
Observables provide a two way binding mechanism, and are integrated with the underlying React.js state mechanism.
Given param :foo, type: React::Observable then both the params.foo method and params.foo! methods will be defined, and
the value of foo will have the same semantics as if foo were a state. A detailed discussion can be found here link to two way binding
React state variables are reactive component instance variables that cause rerendering when they change.
State variables are accessed via the state instance method which works like the params method. Like normal instance variables, state variables are created when they are first accessed, so there is no explicit declaration.
To access the value of a state variable foo you would say state.foo.
To initialize or update a state variable you use its name followed by !. For example state.foo! [] would initialize foo to an empty array. Unlike the assignment operator, the update method returns the current value (before it is changed.)
Often state variables have complex values with their own internal state, an array for example. The problem is as you push new values onto the array you are not changing the object pointed to by the state variable, but its internal state.
To handle this use the same "!" suffix with no parameter, and then apply any update methods to the resulting value. The underlying value will be updated, and the underlying system will be notified that a state change has occurred.
For example
state.foo! [] # initialize foo (returns nil)
...later...
state.foo! << 12 # push 12 onto foo's array
...or...
state.foo! {}
state.foo![:house => :boat]The rule is simple: anytime you are updating a state variable follow it by the "!".
A state variables update method (name followed by "!") can optionally accept one parameter. If a parameter is passed, then the method will 1) save the current value, 2) update the value to the passed parameter, 3) update the underlying react.js state object, 4) return the saved value.
If no parameter is passed, then an object of class React::Observable is created. React::Observables proxy all method calls to whatever value they are initialized with, and then when the method returns they call a notification callback. In the case of state variables the callback will tell react.js that state has changed.
The force_update! instance method causes the component to re-render. Usually this is not necessary as rendering will occur when state variables change, or new params are passed. For a good example of using force_update! see the Alarm component above. In this case there is no reason to have a state track of the time separately, so we just call force_update! every second.
Returns the dom_node that this component instance is mounted to. Typically used in the after_mount callback to setup linkages to external libraries.
Along with params components may be passed a block which is used to build the components children.
The instance method children returns an enumerable that is used to access the unrendered children of a component.
class IndentEachLine < React::Component::Base
param by: 20, type: Integer
def render
div do
children.each_with_index do |child, i|
child.render(style: {"margin-left" => params.by*i})
end
end
end
end
Element['#container'].render do
IndentEachLine(by: 100) do
div {"Line 1"}
div {"Line 2"}
div {"Line 3"}
end
end