Module: React::Component::ClassMethods

Defined in:
lib/react/component/class_methods.rb

Overview

class level methods (macros) for components

Instance Method Summary collapse

Instance Method Details

#add_item_to_tree(current_tree, new_item) ⇒ Object



206
207
208
209
210
211
212
213
214
215
# File 'lib/react/component/class_methods.rb', line 206

def add_item_to_tree(current_tree, new_item)
  if Native(current_tree).class != Native::Object || new_item.length == 1
    new_item.inject { |a, e| { e => a } }
  else
    Native(current_tree)[new_item.last] = add_item_to_tree(
      Native(current_tree)[new_item.last], new_item[0..-2]
    )
    current_tree
  end
end

#append_backtrace(message_array, backtrace) ⇒ Object



26
27
28
29
# File 'lib/react/component/class_methods.rb', line 26

def append_backtrace(message_array, backtrace)
  message_array << "    #{backtrace[0]}"
  backtrace[1..-1].each { |line| message_array << line }
end

#backtrace(*args) ⇒ Object



10
11
12
13
# File 'lib/react/component/class_methods.rb', line 10

def backtrace(*args)
  @dont_catch_exceptions = (args[0] == :none)
  @backtrace_off = @dont_catch_exceptions || (args[0] == :off)
end

#collect_other_params_as(name) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
# File 'lib/react/component/class_methods.rb', line 107

def collect_other_params_as(name)
  validator.allow_undefined_props = true
  define_method(name) do
    @_all_others ||= self.class.validator.undefined_props(props)
  end

  validator_in_lexial_scope = validator
  props_wrapper.define_method(name) do
    @_all_others ||= validator_in_lexial_scope.undefined_props(props)
  end
end

#default_propsObject



61
62
63
# File 'lib/react/component/class_methods.rb', line 61

def default_props
  validator.default_props
end

#define_param(name, param_type) ⇒ Object



73
74
75
# File 'lib/react/component/class_methods.rb', line 73

def define_param(name, param_type)
  props_wrapper.define_param(name, param_type, self)
end

#define_state(*states, &block) ⇒ Object



119
120
121
122
123
124
125
126
127
# File 'lib/react/component/class_methods.rb', line 119

def define_state(*states, &block)
  default_initial_value = (block && block.arity == 0) ? yield : nil
  states_hash = (states.last.is_a?(Hash)) ? states.pop : {}
  states.each { |name| states_hash[name] = default_initial_value }
  (self.initial_state ||= {}).merge! states_hash
  states_hash.each do |name, initial_value|
    define_state_methods(self, name, &block)
  end
end

#define_state_methods(this, name, from = nil, &block) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/react/component/class_methods.rb', line 140

def define_state_methods(this, name, from = nil, &block)
  this.define_method("#{name}") do
    React::Component.deprecation_warning "Direct access to state `#{name}`.  Use `state.#{name}` instead." if from.nil? || from == this
    State.get_state(from || self, name)
  end
  this.define_method("#{name}=") do |new_state|
    React::Component.deprecation_warning "Direct assignment to state `#{name}`.  Use `#{(from && from != this) ? from : 'state'}.#{name}!` instead."
    yield name, State.get_state(from || self, name), new_state if block && block.arity > 0
    State.set_state(from || self, name, new_state)
  end
  this.define_method("#{name}!") do |*args|
    React::Component.deprecation_warning "Direct access to state `#{name}`.  Use `state.#{name}` instead."  if from.nil? or from == this
    if args.count > 0
      yield name, State.get_state(from || self, name), args[0] if block && block.arity > 0
      current_value = State.get_state(from || self, name)
      State.set_state(from || self, name, args[0])
      current_value
    else
      current_state = State.get_state(from || self, name)
      yield name, State.get_state(from || self, name), current_state if block && block.arity > 0
      State.set_state(from || self, name, current_state)
      Observable.new(current_state) do |update|
        yield name, State.get_state(from || self, name), update if block && block.arity > 0
        State.set_state(from || self, name, update)
      end
    end
  end
end

#export_component(opts = {}) ⇒ Object



185
186
187
188
189
190
191
192
# File 'lib/react/component/class_methods.rb', line 185

def export_component(opts = {})
  export_name = (opts[:as] || name).split('::')
  first_name = export_name.first
  Native(`window`)[first_name] = add_item_to_tree(
    Native(`window`)[first_name],
    [React::API.create_native_react_class(self)] + export_name[1..-1].reverse
  ).to_n
end

#export_state(*states, &block) ⇒ Object



129
130
131
132
133
134
135
136
137
138
# File 'lib/react/component/class_methods.rb', line 129

def export_state(*states, &block)
  default_initial_value = (block && block.arity == 0) ? yield : nil
  states_hash = (states.last.is_a?(Hash)) ? states.pop : {}
  states.each { |name| states_hash[name] = default_initial_value }
  State.initialize_states(self, states_hash)
  states_hash.each do |name, initial_value|
    define_state_methods(self, name, self, &block)
    define_state_methods(singleton_class, name, self, &block)
  end
end

#imports(component_name) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
# File 'lib/react/component/class_methods.rb', line 194

def imports(component_name)
  React::API.import_native_component(
    self, React::API.eval_native_react_component(component_name)
  )
  define_method(:render) {} # define a dummy render method - will never be called...
rescue Exception => e # rubocop:disable Lint/RescueException : we need to catch everything!
  raise "#{self} cannot import '#{component_name}': #{e.message}."
  # rubocop:enable Lint/RescueException
ensure
  self
end

#native_mixin(item) ⇒ Object



169
170
171
# File 'lib/react/component/class_methods.rb', line 169

def native_mixin(item)
  native_mixins << item
end

#native_mixinsObject



173
174
175
# File 'lib/react/component/class_methods.rb', line 173

def native_mixins
  @native_mixins ||= []
end

#optional_param(name, options = {}) ⇒ Object



102
103
104
105
# File 'lib/react/component/class_methods.rb', line 102

def optional_param(name, options = {})
  React::Component.deprecation_warning "`optional_param` is deprecated, use `param param_name: default_value` instead."
  validator.optional(name, options)
end

#param(*args) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/react/component/class_methods.rb', line 77

def param(*args)
  if args[0].is_a? Hash
    options = args[0]
    name = options.first[0]
    default = options.first[1]
    options.delete(name)
    options.merge!({default: default})
  else
    name = args[0]
    options = args[1] || {}
  end
  if options[:default]
    validator.optional(name, options)
  else
    validator.requires(name, options)
  end
end

#params(&block) ⇒ Object



65
66
67
# File 'lib/react/component/class_methods.rb', line 65

def params(&block)
  validator.build(&block)
end

#process_exception(e, component, reraise = nil) ⇒ Object



15
16
17
18
19
20
21
22
23
24
# File 'lib/react/component/class_methods.rb', line 15

def process_exception(e, component, reraise = nil)
  message = ["Exception raised while rendering #{component}"]
  if e.backtrace && e.backtrace.length > 1 && !@backtrace_off
    append_backtrace(message, e.backtrace)
  else
    message[0] += ": #{e.message}"
  end
  `console.error(#{message.join("\n")})`
  raise e if reraise || @dont_catch_exceptions
end

#prop_typesObject



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/react/component/class_methods.rb', line 45

def prop_types
  if self.validator
    {
      _componentValidator: %x{
        function(props, propName, componentName) {
          var errors = #{validator.validate(Hash.new(`props`))};
          var error = new Error(#{"In component `#{name}`\n" + `errors`.join("\n")});
          return #{`errors`.count > 0 ? `error` : `undefined`};
        }
      }
    }
  else
    {}
  end
end

#props_wrapperObject



69
70
71
# File 'lib/react/component/class_methods.rb', line 69

def props_wrapper
  @props_wrapper ||= Class.new(PropsWrapper)
end

#reactrb_component?Boolean

Returns:

  • (Boolean)


6
7
8
# File 'lib/react/component/class_methods.rb', line 6

def reactrb_component?
  true
end

#render(container = nil, params = {}, &block) ⇒ Object



31
32
33
34
35
36
37
38
39
# File 'lib/react/component/class_methods.rb', line 31

def render(container = nil, params = {}, &block)
  define_method :render do
    if container
      React::RenderingContext.render(container, params) { instance_eval(&block) if block }
    else
      instance_eval(&block)
    end
  end
end

#required_param(name, options = {}) ⇒ Object Also known as: require_param



95
96
97
98
# File 'lib/react/component/class_methods.rb', line 95

def required_param(name, options = {})
  React::Component.deprecation_warning "`required_param` is deprecated, use `param` instead."
  validator.requires(name, options)
end

#static_call_back(name, &block) ⇒ Object



177
178
179
# File 'lib/react/component/class_methods.rb', line 177

def static_call_back(name, &block)
  static_call_backs[name] = block
end

#static_call_backsObject



181
182
183
# File 'lib/react/component/class_methods.rb', line 181

def static_call_backs
  @static_call_backs ||= {}
end

#validatorObject



41
42
43
# File 'lib/react/component/class_methods.rb', line 41

def validator
  @validator ||= Validator.new(self)
end