question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Is it a normal behavior to have all element properties stringified (through hast-to-hyperscript) ?

See original GitHub issue

Hi, thanks for your work !!

here’s a bit of context.

I’m developing a common mark generic extensions plugin, supporting this kind of syntax: !Element[content](argument){ properties }

I’m using !Icon[My-tooltip](my-icon){ floating } for testing

My remark inline tokenizer returns this node:

{
  type: 'extension',
  data: {
    hName: 'Icon',
    hProperties: {
      tooltip: 'My-tooltip',
      icon: 'my-icon'
      floating: true
    },
  }
})

Notice the boolean property named floating.

I can properly have my corresponding react component TooltipIcon render with the following snippet (es6):

import remark from "remark"
import reactRenderer from "remark-react"
import merge from "deepmerge"
import sanitizeGhSchema from "hast-util-sanitize/lib/github.json"

import TooltipIcon from "../TooltipIcon"
import genericExtensions from "./remark-commonmark-generic-extensions.js"

remark()
    .use(genericExtensions, {
      elements: {
        Icon: {
          attributeMap: {
            content: "tooltip",
            argument: "icon",
          },
          attributeDefaultValues: {
            floating: true,
          }
        }
      }
    })
    .use(reactRenderer, {
      sanitize: merge(sanitizeGhSchema, {
        tagNames: [
          "Icon",
        ],
        attributes: {
          Icon: [
            "className",
            "tooltip",
            "icon",
            "floating",
          ],
        },
      }),
      remarkReactComponents: {
        Icon: TooltipIcon
      },
    })
    .processSync(body, {
      commonmark: true,
    })

Whereas my floating property is effectively boolean inside the HAST tree generated by remark, it is stringified by hast-to-hyperscript at this line, called here in remark-react.

In order to avoid a react PropTypes type warning, i’m actually forced to also allow String in addition to Boolean propTypes for the floating property inside my component. I then coerce the floating property back to boolean, in order for the subcomponent (which requires floating to be boolean) to be happy.

Here’s my TooltipIcon component:

import React, { PropTypes } from "react"
import IconButton from "react-toolbox/lib/button"
import Tooltip from "react-toolbox/lib/tooltip"

const TooltipButton = Tooltip(IconButton)

const TooltipIcon = props => {

  const { floating, ...otherProps } = props
  if (floating === "true") {
    otherProps.floating = true
  }

  return (
    <TooltipButton
      { ...otherProps }
    />
  )
}

TooltipIcon.propTypes = {
  floating: PropTypes.oneOfType([
    PropTypes.bool,
    PropTypes.string,
  ]),
  tooltip: PropTypes.any,
  theme: PropTypes.object,
}

export default TooltipIcon

I hope you get the general idea, and if you can tell if it’s a requirement to have every property stringified. Because in this case only String properties can be passed to React if i’m not mistaken.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:13 (13 by maintainers)

github_iconTop GitHub Comments

2reactions
medfreemancommented, May 9, 2017

Do you know if React’s VDOM accepts non-strings in normal elements too, or just for components?

The answer is basically yes, but the processing differs depending on the node / attribute:

  • style, dangerouslySetInnerHTML, children, __html, suppressContentEditableWarning are processed separately, i won’t go into the details, info here (code ref)
  • properties corresponding to event handlers are bound to the passed function
  • if it is on a custom component (i.e. polymer, that contains a dash in its tagname) and the property isn’t reserved and doesn’t contain invalid chars, it goes through setValueForAttribute, is stringified ('' + value) or removed if value is null
  • if not the above, and attribute is in this list (code ref) or a data- or aria- attribute, it goes through setValueForProperty where:
    • if prop has mutationMethod, for now that only applies to the value property and has a value, it is stringified, with exceptions for number validation in input type fields (for browser validation/focus/blur reasons)
    • if prop value should be ignored, it is unset
    • if it has a MUST_USE_PROPERTY flag (ref. here), it is passed as is to the corresponding dom object property
    • if not one of the above, and:
      • element namespaced (i.e. svg) -> namespaced and stringified
      • is boolean: AND true ->set attribute to empty string / OTHER value -> stringified
  • The “unknown” properties are dropped for now, but should be passed on from ~v.17, see facebook/react#140, current PR facebook/react#7311

References in order:

Differences with html attributes

All Supported HTML Attributes

updateDOMProperties

setValueForProperty and setValueForAttribute reference

shouldIgnoreValue

propertyInfo initialization

propertyInfo config definition

mutator function

facebook/react#140 facebook/react#7311

1reaction
medfreemancommented, May 22, 2017

Should i just make a PR updating hast-to-hyperscript ?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Is it a normal behavior to have all element properties ... - GitHub
Whereas my floating property is effectively boolean inside the HAST tree generated by remark, it is stringified by hast-to-hyperscript at ...
Read more >
Since properties order in objects is not guaranteed in ...
Since properties order in objects is not guaranteed in JavaScript, how does JSON.stringify() actually behave? Is the following always true (same ...
Read more >
Enumerability of properties • Deep JavaScript - Exploring JS
Enumerability is an attribute of object properties. In this chapter, we take a closer look at how it is used and how it...
Read more >
Filter Object Properties by Using JSON.stringify
A simple technique to filter JavaScript object properties by using replacer ... Sometimes, we work on the old project that we don't have...
Read more >
JSON Object Examples: Stringify and Parse Methods Explained
Let's make a list of all JSON-unsafe values and anything that isn't on the list can be considered JSON-safe. JSON-unsafe values: * undefined ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found