Skip to content

Conversation

chrisvxd
Copy link
Collaborator

@chrisvxd chrisvxd commented Sep 8, 2020

Blocked by #48, and have based this on that.


What?

Enables custom query selectors, which can eliminate any custom markup.

Instead of this

<html>
  <body>
    <div class="Clock" data-rehydratable="Clock">
      15:21:11
    </div>
  </body>
</html>

You can now have this

<html>
  <body>
    <div class="Clock">
      15:21:11
    </div>
  </body>
</html>

By configuring your rehydrate method with the new getQuerySelector() method

import rehydrate from 'react-from-markup';
import { ClockRehydrator } from 'my-components';

rehydrate(
  root,
  {
    Clock: ClockRehydrator
  },
  {
    getQuerySelector: key => `.${key}`
  }
);

How?

This PR extends replaces reading of the data-rehydratable attribute with a query selector. By default, this query selector will check for data-rehydratable, but this can be overridden using the getQuerySelector param.

You can get quite creative with your selectors, targeting whatever you want.

Breaking changes

This PR contains no breaking changes

Considerations

There is a slight performance penalty to doing this instead of reading the data-rehydratable attribute directly, in particular due to the introduction of some new loops. I'll do my best to point them out via PR line comments.

TODO

  • Tests
  • Docs

@chrisvxd chrisvxd requested a review from simon360 September 8, 2020 11:47
const rehydratorName = el.getAttribute("data-rehydratable");
const rehydratorSelector = Object.keys(options.allSelectors).find(selector =>
el.matches(selector)
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance consideration: This introduces a find loop on each call of rehydratableToReactElement.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth considering switch to for loop:

Source. Need more data.

if (
node.nodeType === Node.ELEMENT_NODE &&
(node as Element).hasAttribute("data-rehydratable")
(node as Element).matches(options.compoundSelector)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance consideration: How does .matches compare to hasAttribute?

);

const compoundSelector = Object.keys(allSelectors).reduce(
(acc: string, selector: string) => `${acc ? `${acc}, ` : ""}${selector}`,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance consideration: Additional loop on each hydrate, but only called once per hydrate.

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

Successfully merging this pull request may close these issues.

1 participant