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

Commit baf71b4

Browse files
committed
wip
1 parent 12949af commit baf71b4

30 files changed

+249
-116
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ Whitespace conventions:
1818
- 1 spaces before normal text
1919
-->
2020

21+
## [0.8.9] - FILL-IN FILL-IN
22+
23+
### Fixed
24+
25+
- Gets rid of react warnings about updating state during render (#155)
26+
- Multiple HAML classes (i.e. div.foo.bar) was not working (regression introduced in 0.8.8)
27+
- Don't send nil (null) to form components as the value string (#157)
28+
- Process `params` (props) correctly when using `Element#on` or `Element#render` (#158)
29+
- Deprecate shallow param compare (#156)
30+
31+
2132
## [0.8.8] - 2016-07-13
2233

2334
### Added

lib/react/api.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def self.native_react_component?(name)
3737
end
3838

3939
def self.create_native_react_class(type)
40-
raise "Provided class should define `render` method" if !(type.method_defined? :render)
40+
raise "Provided class should define `render` method" if !(type.respond_to? :render)
4141
render_fn = (type.method_defined? :_render_wrapper) ? :_render_wrapper : :render
4242
# this was hashing type.to_s, not sure why but .to_s does not work as it Foo::Bar::View.to_s just returns "View"
4343
@@component_classes[type] ||= %x{

lib/react/component.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ def update_react_js_state(object, name, value)
113113
end
114114
end
115115

116-
def render
117-
raise 'no render defined'
118-
end unless method_defined?(:render)
116+
# def render
117+
# raise 'no render defined'
118+
# end unless respond_to?(:render)
119119

120120
def _render_wrapper
121121
State.set_state_context_to(self, true) do

lib/react/component/class_methods.rb

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ module React
22
module Component
33
# class level methods (macros) for components
44
module ClassMethods
5-
65
def reactrb_component?
76
true
87
end
@@ -29,15 +28,26 @@ def append_backtrace(message_array, backtrace)
2928
end
3029

3130
def render(container = nil, params = {}, &block)
32-
define_method :render do
33-
if container
31+
if container
32+
container = container.type if container.is_a? React::Element
33+
define_method :render do
3434
React::RenderingContext.render(container, params) { instance_eval(&block) if block }
35-
else
36-
instance_eval(&block)
3735
end
36+
else
37+
define_method(:render) { instance_eval(&block) }
3838
end
3939
end
4040

41+
# method missing will assume the method is a class name, and will treat this a render of
42+
# of the component, i.e. Foo::Bar.baz === Foo::Bar().baz
43+
44+
def method_missing(name, *args, &children)
45+
Object.method_missing(name, *args, &children) unless args.empty?
46+
React::RenderingContext.render(
47+
self, class: React::Element.haml_class_name(name), &children
48+
)
49+
end
50+
4151
def validator
4252
@validator ||= Validator.new(self)
4353
end

lib/react/component/tags.rb

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
# class HtmlTagWrapper
2+
# def initialize(name)
3+
# @name = name
4+
# end
5+
# def to_s
6+
# @name
7+
# end
8+
# def method_missing(n)
9+
#
10+
# end
11+
12+
113
module React
214
module Component
315
# contains the name of all HTML tags, and the mechanism to register a component
@@ -26,18 +38,34 @@ def present_as_node(component, *params, &children)
2638

2739
# define each predefined tag as an instance method
2840

41+
42+
43+
2944
HTML_TAGS.each do |tag|
3045
define_method(tag) do |*params, &children|
3146
React::RenderingContext.render(tag, *params, &children)
3247
end
33-
alias_method tag.upcase, tag
34-
const_set tag.upcase, tag
48+
if tag != :div
49+
alias_method tag.upcase, tag
50+
const_set tag.upcase, tag
51+
else
52+
alias_method tag.upcase, tag
53+
#const_set tag.upcase, React.create_element(tag)
54+
#Object.const_set tag.upcase, Class.new(HtmlTagWrapper)
55+
end
3556
# handle deprecated _as_node style
3657
define_method("#{tag}_as_node") do |*params, &children|
3758
React::RenderingContext.build_only(tag, *params, &children)
3859
end
3960
end
4061

62+
def self.html_tag_class_for(tag)
63+
downcased_tag = tag.downcase
64+
if tag =~ /[A-Z]+/ && HTML_TAGS.include?(downcased_tag)
65+
Object.const_set tag, React.create_element(downcased_tag)
66+
end
67+
end
68+
4169
# use method_missing to look up component names in the form of "Foo(..)"
4270
# where there is no preceeding scope.
4371

@@ -92,6 +120,8 @@ def find_component(name)
92120

93121
def lookup_const(name)
94122
return nil unless name =~ /^[A-Z]/
123+
#html_tag = React::Component::Tags.html_tag_class(name)
124+
#return html_tag if html_tag
95125
scopes = self.class.name.to_s.split('::').inject([Module]) do |nesting, next_const|
96126
nesting + [nesting.last.const_get(next_const)]
97127
end.reverse

lib/react/element.rb

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ def on(*event_names, &block)
4444
# Used for elements that are not yet in DOM, i.e. they are provided as children
4545
# or they have been explicitly removed from the rendering context using the delete method.
4646

47-
def render(props = {})
47+
def render(props = {}, &new_block)
4848
if props.empty?
4949
React::RenderingContext.render(self)
5050
else
5151
props = API.convert_props(props)
5252
React::RenderingContext.render(
5353
Element.new(`React.cloneElement(#{to_n}, #{props.shallow_to_n})`,
54-
type, properties.merge(props), block)
54+
type, properties.merge(props), block),
5555
)
5656
end
5757
end
@@ -77,20 +77,34 @@ def as_node
7777
# params may be provide to each class (but typically only to the last for easy reading.)
7878

7979
def method_missing(class_name, args = {}, &new_block)
80-
class_name = class_name.gsub(/__|_/, '__' => '_', '_' => '-')
81-
new_props = properties.dup
82-
new_props[:className] = "\
83-
#{class_name} #{new_props[:className]} #{args.delete(:class)} #{args.delete(:className)}\
84-
".split(' ').uniq.join(' ')
85-
new_props.merge! args
80+
return dup.render.method_missing(class_name, args, &new_block) unless rendered?
8681
React::RenderingContext.replace(
8782
self,
88-
RenderingContext.build { RenderingContext.render(type, new_props, &new_block) }
83+
RenderingContext.build do
84+
RenderingContext.render(type, build_new_properties(class_name, args), &new_block)
85+
end
8986
)
9087
end
9188

89+
def rendered?
90+
React::RenderingContext.rendered? self
91+
end
92+
93+
def self.haml_class_name(class_name)
94+
class_name.gsub(/__|_/, '__' => '_', '_' => '-')
95+
end
96+
9297
private
9398

99+
def build_new_properties(class_name, args)
100+
class_name = self.class.haml_class_name(class_name)
101+
new_props = properties.dup
102+
new_props[:className] = "\
103+
#{class_name} #{new_props[:className]} #{args.delete(:class)} #{args.delete(:className)}\
104+
".split(' ').uniq.join(' ')
105+
new_props.merge! args
106+
end
107+
94108
# built in events, events going to native components, and events going to reactrb
95109

96110
# built in events will have their event param translated to the Event wrapper

lib/react/object.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Lazy load HTML tag constants in the form DIV or A
2+
# This is needed to allow for a HAML expression like this DIV.my_class
3+
class Object
4+
class << self
5+
alias _reactrb_tag_original_const_missing const_missing
6+
7+
def const_missing(const_name)
8+
# Opal uses const_missing to initially define things,
9+
# so we always call the original, and respond to the exception
10+
_reactrb_tag_original_const_missing(const_name)
11+
rescue StandardError => e
12+
React::Component::Tags.html_tag_class_for(const_name) || raise(e)
13+
end
14+
end
15+
end

0 commit comments

Comments
 (0)