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

Skip second argument in React.createElement() #45

Closed
PascalPixel opened this issue Apr 23, 2018 · 6 comments
Closed

Skip second argument in React.createElement() #45

PascalPixel opened this issue Apr 23, 2018 · 6 comments

Comments

@PascalPixel
Copy link

Do you want to request a feature or report a bug?
A feature

What is the current behavior?
React.createElement(component, props, children), when props aren't needed, you still have to pass null or {} as a second argument.

What is the proposal?
Being allowed to omit the second argument, allowing this:

import React from 'react'
import Foo from './Foo'
import Bar from './Bar'

const o = React.createElement

const App = () =>
  o('div',
    o('h1', 'Hello'),
    o(Foo),
    'Ok!',
    o('p', 'How are you?'),
    o(Foo,
      o(Bar, { key: 'hi' },
        o('span', 'Heya!')
      )
    )
  )

Demo code?
I currently, very naively, use this:

function o () {
  var argumentsArray = Array.from(arguments)
  var x = argumentsArray[1]
  if (typeof x === 'string' || typeof x === 'number' || Array.isArray(x) || (typeof x === 'object' && Object.keys(x)[0] === '$$typeof')) {
    argumentsArray.splice(1, 0, {})
  }
  return React.createElement.apply(this, argumentsArray)
}
@streamich
Copy link

streamich commented Apr 23, 2018

Here is user space solution:

const h = React.createElement;

React.createElement = (type, props, ...children) => {
  if (typeof props !== 'object') {
    children = [props, ...children];
    props = {};
  }

  return h(type, props, ...children);
};

@dantman
Copy link

dantman commented Apr 23, 2018

There's a library directly linked to by the React documentation that offers the syntax you're looking for.

https://github.com/mlmorg/react-hyperscript

@PascalPixel
Copy link
Author

@streamich Thank you for your code:

  • typeof == 'object' does not distinguish between arrays and objects (both are true)
  • children can be an object as well
  • my own user space solution checks if the first key in the object is $$typeof
  • this is still very crude, could you improve my code?

@dantman hyperscript needs the children to be in an array, createElement doesn't, so using it actually adds a bit more overhead, that's why I'm looking to use createElement itself, or is it easy to turn off arrays in hyperscript somehow?

@dantman
Copy link

dantman commented Apr 23, 2018

@Superpencil Seems like a pretty small difference, but it does look like there is an issue on the topic and there is a branch in the repo linked that implements the behaviour you want.

I'd think it would be easier to convince the library to implement the behaviour you want than to get React to change how the API works for a use case that React.createElement isn't intended for.

@j-f1
Copy link

j-f1 commented Apr 23, 2018

This has a possible security issue: if you pass a user-provided string as the first child of a component without props, the user may be able to misuse your API, allowing them to insert any props they’d like into the component.

@PascalPixel
Copy link
Author

@dantman you're right, it's a small difference, I'll pursue the issue there, thank you!
@j-f1 Thank you! I was sharing my code in the hope someone would be able to point out some security issue :)

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

4 participants