Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More ref magic #149

Open
edemaine opened this issue Jul 10, 2022 · 0 comments
Open

More ref magic #149

edemaine opened this issue Jul 10, 2022 · 0 comments

Comments

@edemaine
Copy link
Contributor

Inspired by @fabiospampinato's #96 (comment), here are some ideas for solving some current issues with ref:

Multiple refs on a common element

Currently it's annoying to "merge" two refs together into one ref attribute. For example, if you want props.ref to be called and to set a local ref variable, you need to do something like this:

<div ref={(r) => props.ref(ref = r)}/>`

This is fairly short but not particularly intuitive or readable. Possible solutions:

  1. We could make ref-1={ref} ref-2={props.ref} work, i.e., ref-NUMBER could work just like ref, but they stack like directives do. (Or perhaps ref:1={ref} ref:2={props.ref}, but see other suggestion for that syntax below.)
  2. We could make ref={[ref, props.ref]} work (Fabio's proposal). Only inline arrays would be supported, just like event handlers already have special meaning for inline arrays.

In either case, we'd end up with a ref function like this (inlined for Element creation as in <div/>):

ref(r$) {
  const _ref$ = ref;
  typeof _ref$ === "function" ? _ref$(r$) : ref = r$;
  props.ref(r$);
}

Components that want to provide multiple refs

Sometimes a component wants to expose multiple DOM elements (or other data, e.g. API functionality) to the parent. Currently that needs to be done via callback functions, like so:

<Component apiRef={(r) => apiRef = r} viewRef={(r) => viewRef = r}/>

Instead, we could imagine a ref: prefix that has the same syntactic sugar that ref does:

<Component ref:api={apiRef} ref:view={viewRef}/>

This would compile to:

createComponent(Component, {
  ["ref:api"](r$) {
    const _ref$ = apiRef;
    typeof _ref$ === "function" ? _ref$(r$) : apiRef = r$;
  },
  ["ref:view"](r$) {
    const _ref$ = viewRef;
    typeof _ref$ === "function" ? _ref$(r$) : viewRef = r$;
  },
});

So the component could be defined like this:

function Component(props) {
  props['ref:api']?.({ ... });
  return <div ref={props['ref:view']}>...</div>;
}

If use:___ ends up being syntactic sugar for ref, we could add functionality for multiple refs with syntax like this:

<Component use-api:apiDirective use-view:viewDirective/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant