hyper-react
hyper-react copied to clipboard
add `to_key` method to object
Components can be provided a key, via the special key
parameter that ensures when rendering lists of components the ordering does not change, and speeds up the rendering of the list.
...
UL do
MyModel.each do |record|
DisplayRecord(record: record, key: record.id)
end
end
...
typically you can use some data associated with the values being displayed (like record.id
above) or the ruby object_id, or some other unique identifier depending on the contents of the list item.
For HyperModels (and probably other places too) this can be difficult. The above example for instance only works if all the records are saved (i.e. have ids). You can't use record.object_id
since there is no guarantee that on the next rendering the record instance will be the same object_id, so you have use record.backing_record.object_id
which is gross and relies on knowing the inards of HyperModel.
The solution is to add a to_key
method to the base ruby Object
class and to have the key parameter automatically have to_key
applied to it. The default to_key
method will return self.object_id
, but this can be overwritten as needed. I.e. ActiveRecord::Base can override as self.backing_record.object_id
.
Now we can write DisplayRecord(record: record, key: record)
shorter, sweeter, and works.
Also in keeping with POLS, strings, symbols, booleans and number objects will return themselves.
class Object
def to_key
object_id
end
end
class String
def to_key
self
end
end
class Number
def to_key
self
end
end
class Boolean
def to_key
self
end
end
class Foo
end
class Bar
def self.new_bar_counter
@bar_counter = (@bar_counter && @bar_counter+1) || 0
end
def initialize
@to_key = "Bar ##{Bar.new_bar_counter}"
end
attr_reader :to_key
end
puts Object.new.to_key
puts "hello".to_key
puts 12.to_key
puts true.to_key
puts Foo.new.to_key
puts Bar.new.to_key
puts Bar.new.to_key
Produces
5206
hello
12
true
5208
Bar #0
Bar #1
As well as adding the method to the classes per above, you also have to add these lines here
elsif key == "key"
props["key"] = value.to_key
...
This is nice. The way it's laid out is also backwards compatible because record.id
or record.object_id
in existing code returns a number, and Number#to_key == self
.
Hi, I think I can help with this issue.