levand / quiescent

A lightweight ClojureScript abstraction over ReactJS
Eclipse Public License 1.0
613 stars 46 forks source link

implement a generic solution for setting a react key on a component from outside the component. #59

Open shyblower opened 8 years ago

shyblower commented 8 years ago

This has the advantage that neither every component that may be part of a sequence has to implement a :keyfn function nor does the component have to know that fact and how to generate a key which will not be needed by the component for any other purpose.

To keep the current API and since the key actually IS metadata this is accomplished by setting metadata on the component's value at call time using the with-key function, e.g. (MyComponent (with-key value key) ...), which will override :keyfn.

The only restriction for this to work is that the component's value has to be a datatype which may carry metadata (implements the IWithMeta interface) like vectors, hashmaps, etc...

shyblower commented 8 years ago

Another solution for setting the key from outside while keeping the API intact would be binding a dynamic var around the component call. While this would allow for scalar component values not implementing the IWithMeta interface on keyed components, it would have the disadvantage of every child of the component inheriting the same key unless rebound. While this should not affect the functionality of React's key mechanism since only siblings of an array or iterator (or a sequence in Clojurescript) must use distinct keys, it feels a bit awkward to me ... although I'm not entirely convinced that it actually is ... ... another problem may be that it will override the :keyfn function on its children though in my opinion the :keyfn mechanism shouldn't be used anyway as briefly laid out in my commit message.

shyblower commented 8 years ago

I have improved the 'with-key' technique by using a deftype instead of metadata thus allowing to use also scalar values as component state.