Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

Explore alternative approaches of UIX components implementation in React #39

Closed
darwin opened this issue Jan 22, 2020 · 4 comments
Closed

Comments

@darwin
Copy link
Contributor

darwin commented Jan 22, 2020

My issue is that currently each UIX component creates two backing react components. React.memo which wraps a function component derived from UIX component (defn). I understand that memo wrapping is needed to implement component update optimization using clojure semantic for equality.

But this has several drawbacks:

  1. component tree depth is effectively doubled, e.g. in React Devtools
  2. memo wrapping is not always needed and can add unecessary overhead, e.g. when having a component with constant props (see[1])

I'm no React expert. Just looked briefly at the implementation. I think there are two possible avenues to explore:

  1. use old-school React class components with shouldComponentUpdate - I know that function components are more modern and fit better to cljs, but for above reasons I would not rule this out
  2. keep an eye on ReactFundamentalComponent type[2]. There is no specs/docs right now. But from the code I believe this might be preferrable way how to implement uix-like library-driven React components in the future.

In current implementation I would also consider:

  1. make memo wrapping optional - e.g. it could be disabled for dev work via a config, or it could be disabled on component-by-component basis using metadata

No hurry. Just ideas. I'm happy to learn about design decisions behind current implementaion. It is very likely that I don't see all reasons.

[1] https://kentcdodds.com/blog/usememo-and-usecallback
[2] facebook/react#16049

@roman01la
Copy link
Owner

roman01la commented Jan 22, 2020

This was raised already at least once.

Memo components in DevTools

Since React favors composition inheritance having lots of wrappers is a common observation and React DevTools has a filter specifically for such cases, see https://github.com/roman01la/uix#react-devtools

Using old-school React class components

This would basically turn UIx into Reagent. Hooks are not supported in class-based components. So this is definitely not an option.

Memo wrapping is not always needed and can add unnecessary overhead

I agree that sometimes there are cases when data is structured in such a way that equality check should traverse the whole thing. But I've already made a couple of apps with UIx and having memo turned on by default got me a better performance than not having memo. It would be nice to selectively turn off memo, which leads to the next point.

Make memo wrapping optional

I'd like to have a mechanism to disable memo per-component, but metadata doesn't work here, because ClojureScript doesn't have Vars, they are only dev-time in REPL. It still can be implemented, but not as elegant as having meta

(defn button [] ...)
(uix.core/no-memo button) ;; this will setup a flag telling the runtime to not wrap with memo
;; or it could be a macro
(defpure button [] ...) ;; but I don't like having a macro specifically to undo memo

@roman01la
Copy link
Owner

Adding a global flag to disable memo is an option as well

@roman01la
Copy link
Owner

Added uix.core.alpha/no-memoize! that disables memoization for a given component a9166e5

@darwin
Copy link
Contributor Author

darwin commented Feb 10, 2020

Just for record, I found an interesting discussion here, might be related:
reactjs/rfcs#108

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants