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

Use setAttribute, not properties to fix SVG update #279

Merged
merged 7 commits into from Sep 23, 2020

Conversation

MaxDesiatov
Copy link
Collaborator

Property assignment does not update SVG elements. We may want to use properties instead of setAttribute in the future for optimizations. For now I think that setAttribute works in all cases, including SVG, and seems safer to me.

Resolves #278.

@MaxDesiatov MaxDesiatov added the bug Something isn't working label Sep 22, 2020
@j-f1
Copy link
Member

j-f1 commented Sep 22, 2020

This causes a regression in the TextField demo — try typing in the first field then the second field on both main and this branch. Ultimately the solution imo is to have a list of keys that should be set as properties instead of attributes.

@MaxDesiatov
Copy link
Collaborator Author

I've introduced a new HTMLAttribute type to apply updates cleanly. There's no regression anymore, at least in the TextField example 🙂

Co-authored-by: Jed Fox <git@jedfox.com>
@carson-katri
Copy link
Member

carson-katri commented Sep 22, 2020

Is the isUpdatedAsProperty a requirement for certain attributes or certain element & attribute combos?

@MaxDesiatov
Copy link
Collaborator Author

IDK, I wasn't able to find any information on this other than some people warning that setAttribute could be somehow slower that property assignment, but no appropriate benchmarks were present to verify this.

@j-f1
Copy link
Member

j-f1 commented Sep 22, 2020

I think it’s usually based on specific names. Here’s React’s file that defines how it handles attributes and properties: https://github.com/facebook/react/blob/92c7e49895032885cffaad77a69d71268dda762e/packages/react-dom/src/shared/DOMProperty.js

Here’s how it’s used for updating DOM nodes: https://github.com/facebook/react/blob/92c7e49895032885cffaad77a69d71268dda762e/packages/react-dom/src/client/DOMPropertyOperations.js#L129-L206

@MaxDesiatov
Copy link
Collaborator Author

MaxDesiatov commented Sep 22, 2020

Interesting that value is not in this list 🤔

// These are the few React props that we set as DOM properties
// rather than attributes. These are all booleans.
[
  'checked',
  // Note: `option.selected` is not updated if `select.multiple` is
  // disabled with `removeAttribute`. We have special logic for handling this.
  'multiple',
  'muted',
  'selected',

@carson-katri
Copy link
Member

If its a set list, could we just automatically check them instead of each element specifying if it needs to be treated as a property?

@MaxDesiatov
Copy link
Collaborator Author

MaxDesiatov commented Sep 22, 2020

I thought about it, but attributes are created everywhere on every render cycle, which means that the check is multiplied by the number of times you use any attribute whatsoever. I'm not sure what's the best way to avoid the check on attribute creation other than hardcoding it as a property at the place of use.

@MaxDesiatov
Copy link
Collaborator Author

Another option would be to forbid attribute creation from a string literal and predefine all attributes in TokamakStaticHTML with an appropriate isUpdatedAsProperty value.

@carson-katri
Copy link
Member

You could do it with type-safety and allow a string literal:

struct HTMLAttribute : ExpressibleByStringLiteral {
  ...
  static let value: Self = .init("value", isUpdatedAsProperty: true)
}

Something like that?

@MaxDesiatov
Copy link
Collaborator Author

Yeah, it wouldn't prevent anyone from still initializing value attribute from a string literal though. Probably still better than the current option...

@carson-katri
Copy link
Member

carson-katri commented Sep 22, 2020

Could make it more explicit with a .custom("myAttribute") initializer instead of a literal.

@MaxDesiatov
Copy link
Collaborator Author

Oh, requiring .custom is going to require changing hundreds of lines, I'd rather do that in a separate PR 😅

@j-f1
Copy link
Member

j-f1 commented Sep 22, 2020

it looks like there are a bunch of files in react-dom/src/client that handle form controls individually (ReactDOMInput.js, ReactDOMSelect.js, ReactDOMOption.js, ReactDOMTextarea.js) which seem to have the value handler inside of them.

Copy link
Member

@j-f1 j-f1 left a comment

Choose a reason for hiding this comment

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

Either way I think this is a good start to unblock our user, and we can iterate more later.

@MaxDesiatov MaxDesiatov merged commit de72316 into main Sep 23, 2020
@MaxDesiatov MaxDesiatov deleted the svg-setattribute branch September 23, 2020 08:13
@MaxDesiatov MaxDesiatov restored the svg-setattribute branch September 23, 2020 08:13
@MaxDesiatov MaxDesiatov deleted the svg-setattribute branch September 23, 2020 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

Successfully merging this pull request may close these issues.

HTML + Binding
3 participants