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

Feature/with react #355

Merged
merged 84 commits into from
May 1, 2018
Merged

Feature/with react #355

merged 84 commits into from
May 1, 2018

Conversation

AndyOGo
Copy link

@AndyOGo AndyOGo commented Mar 21, 2018

Fixes #330 .

Changes proposed in this pull request:

  • adds withReact thunk
  • quickfixes the demo build (adds scss, jsx rosolve, ...)
  • adds todomvc inspired by http://todomvc.com/
  • adds trigger of custom events for limited components (needs to be done for all)

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

Locally

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

@AndyOGo AndyOGo self-assigned this Mar 21, 2018
@AndyOGo AndyOGo requested review from LucaMele and TheDadi March 21, 2018 10:41
@AndyOGo AndyOGo force-pushed the feature/with-react branch 8 times, most recently from 0d16d85 to 1b67be0 Compare March 28, 2018 10:35
@AndyOGo AndyOGo mentioned this pull request Mar 28, 2018
Copy link
Contributor

@LucaMele LucaMele left a comment

Choose a reason for hiding this comment

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

Please update the Readme.md with a short code sample on how to use it (not in the wiki).

Same style and under the one already existing on how to include WC nativly

const { wcNode } = this;

Object.keys(props).forEach((key) => {
if (key === 'children' || key === 'style') {
Copy link
Contributor

Choose a reason for hiding this comment

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

better an external enum with an array of properties

Copy link
Contributor

Choose a reason for hiding this comment

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

and also maybe use this on the property setting on the WC abstract component

Copy link
Author

Choose a reason for hiding this comment

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

Do I understand you correctly, that I should put 'children' and 'style' into a blacklist array? If so absolutely

Copy link
Author

Choose a reason for hiding this comment

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

done

@AndyOGo AndyOGo force-pushed the feature/with-react branch 2 times, most recently from 9529cdf to e517479 Compare March 28, 2018 14:38
@AndyOGo
Copy link
Author

AndyOGo commented Mar 28, 2018

@LucaMele
Regarding docs I have already added an @example doclet.
But sure I can also add it to the readme/contribution file

@AndyOGo
Copy link
Author

AndyOGo commented Mar 29, 2018

hmh, adding a nested <input> within WebComponents seem to lose focus on edit 🤔

react-input-loses-focus-within-ce

@AndyOGo AndyOGo force-pushed the feature/with-react branch from b8af9d5 to 73f0fa2 Compare March 29, 2018 08:23
const AXAHeaderMainReact = withReactBound(AXAHeaderMain);
const AXAHeaderLogoReact = withReactBound(AXAHeaderLogo);

// @todo: super hacky way to keep the input's focus within custom elements
Copy link
Author

@AndyOGo AndyOGo Mar 29, 2018

Choose a reason for hiding this comment

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

@LucaMele
@TheDadi
I distilled a major problem with reactified custom elements consuming <input> children from React. Basically on every re-render the focus is lost of the input control, allowing the user to type only one character at a time 😱

The re-rendering of the parent web-component, removes the whole DOM sub tree at first and the re-inserts it again. This causes the loss of the whole browser intrinsic <input>'s state, like:

  • focus
  • cursor position
  • range selection,
  • etc.
const Example = (({
  onChange,
  value,
}) => (
  <AXAHeader>
    <AXAHeaderMain>
      // the following input control will lose focus at every onKeyup/onClick causing a re-render
      <input type="text" onChange={onChange} value={value} />
    </AXAHeaderMain>
  </AXAHeader>
);

react-input-loses-focus-within-ce

Copy link
Contributor

Choose a reason for hiding this comment

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

mmmm.. not good.. what can we do? and why do we re-render? Can we do sort of one-way-binding?

Copy link
Author

@AndyOGo AndyOGo Mar 29, 2018

Choose a reason for hiding this comment

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

We re-render because on every input's onChange react's state changes - so React triggers a re-render (which is normal behavior for controlled inputs).
The web-components unfortunately detach completely from the DOM (if you remember the deletion speed test) and attaches a newly generated DOM tree...
So I guess diffing should help us here, but need to verify that...

Copy link
Author

Choose a reason for hiding this comment

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

@LucaMele
I found the main glitch. Currently any web-component like <axa-foo bar="baz"> would have even re-rendered if the attribute was set to the exact same value, like:

axaFoo.setAttribute('bar', 'baz'); // no change -> should not trigger re-render, but did before
axaFoo.bar = 'baz'; // no change -> should not trigger re-render, but did before

I fixed this now by checking for shallow equality. And this fixed the input issue too:)

@AndyOGo AndyOGo force-pushed the feature/with-react branch from e821346 to 707d178 Compare March 29, 2018 11:09
@AndyOGo
Copy link
Author

AndyOGo commented Mar 29, 2018

Okay that's a super success story, except the <input> state issue...

const cancelled = fire(this.wcNode, 'axa-click', null, { bubbles: true, cancelable: true, composed: true });

if (!cancelled) {
event.preventDefault();
Copy link
Author

Choose a reason for hiding this comment

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

@LucaMele
preventDefault the original event works :)


handleClick(event, delegateTarget) {
// @todo: would be cool to be able to use props here, cause now it needs JSON.parse...
const index = getAttribute(delegateTarget, 'index');
Copy link
Author

Choose a reason for hiding this comment

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

@LucaMele
Passing the current item's data down to the custom event is possible 👍

@AndyOGo
Copy link
Author

AndyOGo commented Mar 29, 2018

@LucaMele
Now all components need to be examined for custom events and their associated data.


const eventName = dasherize(`${keyFrom2}${key.substring(3)}`);

eventCache[key] = on(wcNode, eventName, props[key], { passive });
Copy link
Author

Choose a reason for hiding this comment

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

@LucaMele
I think it could be convenient to extract the event.detail here optionally, so that consumers can just deal with the data they need.

const key = camelize(name);

this[key] = toProp(newValue);
}

/**
Copy link
Author

@AndyOGo AndyOGo Mar 30, 2018

Choose a reason for hiding this comment

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

@LucaMele
This is suuuper important! It makes sure that the component only re-renders if any attribute has actually changed:)
And it mitigates the nested <input> issue afore mentioned 🎉

@AndyOGo
Copy link
Author

AndyOGo commented Mar 30, 2018

@LucaMele
This is ready to be merged :)

@AndyOGo
Copy link
Author

AndyOGo commented May 1, 2018

I just rebased and it works in chrome with incremental rendering of web-comonents :)

@AndyOGo
Copy link
Author

AndyOGo commented May 1, 2018

I created this follow-up issue #418

@AndyOGo
Copy link
Author

AndyOGo commented May 1, 2018

are there any objections for this to merged?

@AndyOGo AndyOGo merged commit abc9a66 into develop May 1, 2018
@AndyOGo AndyOGo deleted the feature/with-react branch May 1, 2018 10:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Integration POC
5 participants