Coder Social home page Coder Social logo

JSX 2.0 about jsx HOT 136 OPEN

facebook avatar facebook commented on May 5, 2024 274
JSX 2.0

from jsx.

Comments (136)

mohsen1 avatar mohsen1 commented on May 5, 2024 379

Something like Angular ng-if would be nice to have in JSX. Making rendering of an element conditional is not easy in JSX. Maybe adopt Angular 2 *if

from jsx.

lacker avatar lacker commented on May 5, 2024 364
<if {myCondition}>
  <div>This part only gets shown if myCondition is true</div>
</if>

from jsx.

mohsen1 avatar mohsen1 commented on May 5, 2024 257

@BrendanFDMoore I'm aware of those workarounds and we're using them. Since JSX is syntax sugar for React.createElement adding more syntax sugar won't hurt.

In your example the syntax can look like this:

return (
    <div>
      <SomeOtherComponent />
      <MyInnerComponent *if={isInnerComponentIncludedBool} />
    </div>
  );

I guess mentioning Angular earns you lots of downvotes here!

from jsx.

jasonslyvia avatar jasonslyvia commented on May 5, 2024 228

I'd say allow adjacent elements without enclosing tag, really hate additional <div>s like this:

<div>
   <ComponentA />
   <ComponentB />
</div>

from jsx.

syranide avatar syranide commented on May 5, 2024 150

I would be interested in having a real story for comments e.g. #7. {/**/} feels like a hack, and kind of also is as it affects the children when used in certain places. If we actually end up going with #35 (bold, I like it :)) then just properly supporting regular comment syntax is a no-brainer IMHO.

from jsx.

kevinsimper avatar kevinsimper commented on May 5, 2024 133

@mohsen1 @lacker @BrendanFDMoore

You can make it as easy as angular if like this, so I don't see any need for an if tag

{ somethingTrue &&
  <div>Will only show if somethingTrue is true</div>
}

from jsx.

nkohari avatar nkohari commented on May 5, 2024 121

I find that assigning optional components to variables helps for clarity, for example:

function Profile({ user }) {
  let avatar;
  if (user) {
    avatar = <Avatar user={user} />;
  }
  return (
    <div>
      ...whatever the outer component represents...
      {avatar}
    </div>
  );
}

While it would be nice to have direct support in JSX for conditional components, I'm really wary of adding things like <if> or an if=... attribute. Next people will want <for> and <while>... IMHO there's no need to replicate that much JS functionality in JSX.

from jsx.

nkkollaw avatar nkkollaw commented on May 5, 2024 121

Don't fuck it up like Google did with Angular 2, keep the thing compatible with older versions...

from jsx.

bjrmatos avatar bjrmatos commented on May 5, 2024 106

@mohsen1 "It's just JavaScript, not a template language" -> no need to replicate JS functionalities with custom syntax. That is the main benefit of JSX IMO, seriously is so easy to do this with js even if it looks "weird" (for me it is not weird, it is just the syntax of the language)

from jsx.

fdecampredon avatar fdecampredon commented on May 5, 2024 103

I would like to be able to specify some property value with tag :

<SplitContainer
  left={<div>...</div>}
  right={<div>...</div>}
/>
// vs
<SplitContainer>
  <.left>
    <div>...</div>
  </.left>
  <.right>
    <div>...</div>
  </.right>
</SplitContainer>

from jsx.

fab1an avatar fab1an commented on May 5, 2024 89

Automatically bound arrow function that don't allocate a new function everytime:

<div onLoad={@this () => doSomething(blabla)}/>

from jsx.

toddlucas avatar toddlucas commented on May 5, 2024 62

I would like to see class in addition to className and for in addition to htmlFor. I know they're reserved keywords in JavaScript, but JSX isn't JavaScript. It seems like something that would be possible to handle at that level without interfering with JS parsing.

The reason for suggesting this feature is that it makes it more difficult to copy and paste code between environments. There are other considerations, of course, such as embedded, bracketed code (e.g., the way the style attribute value is handled as an object literal).

Regardless, thanks!

from jsx.

gaearon avatar gaearon commented on May 5, 2024 53

Hey folks, just to make it clear, there is no immediate work planned on "JSX 2.0". This is just an issue to batch a few old proposals and also start figuring out how to eventually converge with Reason's version of JSX.

This is an umbrella issue for a few proposals that seem to make sense together. It's not a list of features of "JSX 2.0", nor an announcement of an intent to implement "JSX 2.0".

Also, while we appreciate the input, let's not turn this thread into a giant bikeshed. If you'd like to discuss a specific proposal please create a new issue (unless one already exists which is also likely).

Thanks!

from jsx.

BrendanFDMoore avatar BrendanFDMoore commented on May 5, 2024 51

@mohsen1 our convention for our stateless functional components is to use:

import MyInnerComponent from '../my-inner-component';
function MyOuterComponent({ isInnerComponentIncludedBool }) {
  ...
  return (
    <div>
      <SomeOtherComponent />
      {
        isInnerComponentIncludedBool
        ? <MyInnerComponent />
        : null /*Or some fallback component / messaging*/
      }
    </div>
  );
}

which works pretty well for us. It's pretty clean as long as your outer component props are a clear pre-calculated boolean for show/hide. Because your components don't have any business logic, this should be fine already, right? ;)

edit: the ternary allows us to include an alternative, which we commonly do want, without needing to add an if !someBoolFlag check also.

from jsx.

Pajn avatar Pajn commented on May 5, 2024 51

@mohsen1
It has nothing to do with mentioning Angular but with introducing additional syntax that makes it harder to learn and harder to read without adding any benefit as it's more characters to type than {condition && VDOM} and it's harder to understand (&& will return the lhs if it's falsey as all JS, what will *if do? return null? undefined? rip out the element completely as it was never there?)

Also with #35 and #39 you could do

if (condition) {
  VDOM
}

wich would be JS instead of some special thing

from jsx.

sbussard avatar sbussard commented on May 5, 2024 48

We need more restrictions on how JSX can be written. People are using terrible practices and teaching it to others. Example: child props should only be passed into components via childProps, otherwise it's a mess. There are so many ways to do things but few even ask if they should do it that way.

from jsx.

tachang avatar tachang commented on May 5, 2024 37

Most of these changes wouldn't affect my codebase since I use them sparingly. Comments however would be great. It's kind of insane that normal javascript commenting isn't supported even with all the crazy tool chains we are running.

from jsx.

NekR avatar NekR commented on May 5, 2024 34

I highly doubt that it makes sense to have full backwards compatibility for JSX 2.0. If we are going to improve it -- we should improve.

After all, no one is forced to migrate to JSX 2.0 and you still will be able to write your React apps in JSX 1. React elements/components are just JavaScript calls, so there is no matter what you are using. In some case, if you would like, you probably will be able to use JSX 1 and JSX 2.0 in the same project, e.g. for migration. Just apply new transform for new components.

IMO, that's it.

from jsx.

markshust avatar markshust commented on May 5, 2024 29

this is a common occurance with arrays (and js for that matter):

{(users && users.length) &&
  <ul>
    {users.map(user => <li>{user.username}</li>)}
  </ul>
}

perhaps we can have some sort of special character for this that eliminates the need to check for the object:

{~users.length &&
  <ul>
    {users.map(user => <li>{user.username}</li>)}
  </ul>
}

and perhaps it can even work with other methods:

<ul>
  {~users.map(user => <li>{user.username}</li>)}
</ul>

and object props:

<ul>
  <li>{~user.username}</li>
</ul>

i'm all for anything that can make code more readable with less typing, and still expressive enough to know what is going on.

better yet, if the special character maybe isn't even needed and jsx does the checks automatically.

from jsx.

syranide avatar syranide commented on May 5, 2024 25

@jasonslyvia That's what fragments are for.

from jsx.

syranide avatar syranide commented on May 5, 2024 24

Also, having an actual syntax for fragments would be a very welcome feature (e.g. the previously talked about <>).

from jsx.

caub avatar caub commented on May 5, 2024 24

what would it be for fragments?

const frag = <>
    <div>hello</div>
    <div>world</div>
</>;
// vs 
const frag = [
    <div>hello</div>,
    <div>world</div>
];

then it's the same, you'll need {frag} to insert it.
I think arrays are good enough, similar to DOM fragments, and more powerful to manipulate

comments is a good idea, <!-- --> like html could be fine, but would they be inserted in the DOM (I guess no)? would it conflict with how react uses comments sometimes for text nodes I think

from jsx.

gravitypersists avatar gravitypersists commented on May 5, 2024 22

Sorry I don't have a concrete suggestion, but I feel as though JSX is trying to solve too much (and adding control statements will just add more).

Currently, JSX solves two concerns, one is structure (akin to DOM structure) and the other is for assigning props to elements. I'm not sure how, but is there a way to separate these concerns?

from jsx.

kevinSuttle avatar kevinSuttle commented on May 5, 2024 22

Supporting <style> tags inside components.

from jsx.

mstijak avatar mstijak commented on May 5, 2024 22

I would love to be able to use . in attribute names, similar to Aurelia. JSX syntax doesn't allow it.
<input type="text" value.bind="firstName">.

In Cx, xml namespaces are used for this purpose, but it feels a little bit hacky.
<input type="text" value:bind="firstName">.

from jsx.

brochington avatar brochington commented on May 5, 2024 21

I would like more granular control over what function the JSX is compiled to.

/** @jsx myImageFunc img*/

import React from "react"
import myImageFunc from "./somewhere"

SomeClass extends React.Component {
     render() {
        return (
            <div> // compiled to default, ie. React.createElement
                <img src={...}/> // compiled to myImageFunc
            </div>
        )
    }
}

from jsx.

zertosh avatar zertosh commented on May 5, 2024 18

Request: Syntax to declare properties associated (but not belonging) to a child for consumption by the parent. I don't have opinions on the syntax, but here's an example, that borrows from the "fragment" syntax:

<Layout>
  <{grow={1}}/>
  <Text />

  <{shrink={2}}/>
  <Image />

  <Video />
</Layout>

Above I'm saying that Text has grow=1, and Image has shrink=2, but those props are not for Text and Image, but for Layout. The way to do this in JSX 1.x is to use wrapper elements:

<Layout>
  <Item grow={1}>
    <Text />
  </Item>

  <Item shrink={2}>
    <Image />
  </Item>

  <Video />
</Layout>

But that's really verbose.

cc: @adamjernst

from jsx.

pirate avatar pirate commented on May 5, 2024 17

@kevinSuttle re: Supporting <style> tags in components, I think a current consensus is to use JS template strings (which can span multiple lines), or variables.

<style>{`
    .your-css-here {color: #333;}
`}</style>
// or
<style>{component_style}</style>

I'd rather not introduce a new parsing exception just for <style> tags.

Perhaps a better solution is an escaping mechanism that allows generally including non-JSX text inside of any tags? Maybe something like plain ` without the curly braces, which ties into #21, #55, #64 above:

<style>`
    sdf
`</style>

from jsx.

coreh avatar coreh commented on May 5, 2024 15

IMO, the main downside of do expressions is the triply nested indentation level they require

<div>
  {
    do {
      if (condition) { 
        <Foo />;
      } else {
        <Bar />;
      } 
    }
  }
</div>

Even if you make the indentation more compact, it still doesn't look particularly good:

<div>
  { do { if (condition) { 
    <Foo />;
  } else {
    <Bar />;
  } } }
</div>

I like the idea of { } implicitly starting in a do context, so you could do:

<div>
  {
    if (condition) { 
      <Foo />;
    } else {
      <Bar />;
    } 
  }
</div>

Or, with the more compact indentation:

<div>
  { if (condition) { 
    <Foo />;
  } else {
    <Bar />;
  } }
</div>

If we're going to add support for () in attributes, these could always start in an expression context.

from jsx.

cpojer avatar cpojer commented on May 5, 2024 14

It seems like based on the current wishlist, even if this is a breaking change, we can easily create codemods that go both ways: from JSX to JSX2 and from JSX2 to JSX. No need to freak out.

from jsx.

jmar777 avatar jmar777 commented on May 5, 2024 13

While I don't care for the attribute-based conditional rendering proposal above, I did think it's worth highlighting a couple pain-points with relying primarily on { condition && <Foo /> }:

1. While often suggested as an alternative to if() {}, it doesn't work with all falsy expressions:

For example, consider the following:

{(users && users.length) &&
  <ul>
    {users.map(user => <li>{user.username}</li>)}
  </ul>
}

Unless you've run into this specific issue, it may not obvious why this code is wrong. This code works fine if users is undefined or null, and it works if users is non-empty, but if users is an empty array, then it actually renders a 0. Ultimately this makes sense (React obviously has to let curly-brace expressions emit numerical values), and the workaround is easy, but it's an easy gotcha, nonetheless. Especially when we advocate this syntax as the alternative to first-class if(){} statements, it's easy to see how this bites newcomers in particular.

2. It doesn't play nice with conditionally rendered sibling components:

Please note that this is not a syntax proposal, but instead of having something with "block-level" support, similar to this:

[if (condition)]
  <Foo />
  <Bar />
  <Baz />
[/if]

We instead need:

{ condition && <Foo /> }
{ condition && <Bar /> }
{ condition && <Baz /> }

If the condition itself gets more complex, then the code gets uglier, or alternatively we need to store the result to a temporary variable, which further increases the verbosity. I will note that this particular pain point would be eased by better support for fragments.

TBH I've never seen a specific proposal that I'm overly fond of, but inasmuch as branching logic is integral to all but the most trivial of rendered outputs, I think there's a compelling case to be made for first-class support in JSX.

from jsx.

jkarttunen avatar jkarttunen commented on May 5, 2024 12

Somehow support cleaner, simpler looking syntax like jade/stylus so that co-creation with non-developers gets easier

from jsx.

jamesseanwright avatar jamesseanwright commented on May 5, 2024 12

@toddlucas While className and htmlFor may seem nuanced, they're named after Element.prototype.className and HTMLLabelElement.prototype.htmlFor respectively, which in turn are named to circumvent the conflicts you've described. JSX is simply providing a means of setting these properties.

from jsx.

piotr-oles avatar piotr-oles commented on May 5, 2024 12

I think we can make JSX more readable on conditions with current implementation. What do you think about implementing your custom If component?
<If condition={ someCondition }> <FooComponent> </If>

from jsx.

mvolkmann avatar mvolkmann commented on May 5, 2024 12

As someone who teaches React, I hate having to say "JSX is kind of like HTML which you already know, but it differs in these ways." Making JSX as similar to HTML as possible will appeal to newcomers. That means supporting comments and handling class and for attributes. One of the benefits of JSX is that it uses JavaScript for all conditional and iteration logic. Please do not add custom syntax for those! IMHO, that is a bad feature of other frameworks ... having to learn and use two syntaxes.

from jsx.

kevinSuttle avatar kevinSuttle commented on May 5, 2024 11

But seriously, immutability.

from jsx.

Noitidart avatar Noitidart commented on May 5, 2024 11

I don't get why we use JSX. It just saves a bit of typing but adds a whole bunch of complexity and new rules. I love plain React.createElement, that way I am leveraging javascript, and any questions I have can be answered by anyone that knows javascript.

from jsx.

max-mykhailenko avatar max-mykhailenko commented on May 5, 2024 10

IMHO jsx has only several problems:

  • code comments
  • conditional attributes

JS should have separate context in curly braces.

from jsx.

sebmarkbage avatar sebmarkbage commented on May 5, 2024 10

This thread has turned into a bit of back and forth on particular proposals. It might be better if we move them out as separate GitHub issues for each proposal.

Since a lot of people are asking for control flow. May I suggest that you first consider what #39 will enable before adding new control flow. For example this is perfectly valid if we supported do expressions by default:

return <div>
  Hi!
  {if (bool) <MyComponent /> else <div></div>}
</div>;

from jsx.

fibo avatar fibo commented on May 5, 2024 10

it would be nice to have something like

render () {
  const {
    prop1,
    prop2,
    prop3
  } = this.props

  return (
    <MyComponent prop1 prop2 prop3 />
  )
}

where prop1, prop2 and prop3 are not booleans, but any kind of prop.

Instead of

render () {
  const {
    prop1,
    prop2,
    prop3
  } = this.props

  return (
    <MyComponent prop1={prop1} prop2={prop2} prop3={prop3} />
  )
}

or maybe it could be easier to implement this, to avoid breaking changes with current syntax

render () {
  const {
    prop1,
    prop2,
    prop3
  } = this.props

  return (
    <MyComponent {prop1} {prop2} {prop3} />
  )
}

from jsx.

jmar777 avatar jmar777 commented on May 5, 2024 9

Make whitespace handling more consistent with HTML: facebook/react#4134 (sorry for brevity, currently mobile...).

from jsx.

 avatar commented on May 5, 2024 9

I think the biggest problem of jsx is that jsx does not provide some metadata of evaluated expressions so react don't have the ability to diff only on dynamic data and skip all static bindings.

from jsx.

meznaric avatar meznaric commented on May 5, 2024 8

With current syntax {something && <Component />} when you render a more complex component this introduces another level of indentation. Which in my opinion helps us to spot conditional logic, but does not look as nice.

I think that having multiple ways of doing the same thing adds to overhead when reading the code. It's small but noticeable.

from jsx.

oleksandr-shvets avatar oleksandr-shvets commented on May 5, 2024 7

Hi guys! What do you think about this idea? https://github.com/alexander-shvets/cascading-component-layers-react

from jsx.

kemurphy avatar kemurphy commented on May 5, 2024 7

@caub: There's a subtle difference -- in the example you gave, React will see a single child that's an array and emit warnings about wanting keys. With spread, the equivalent would be:

var h = React.createElement;
ReactDOM.render(
  h('div', null,
    h('span'), 
    h('span'),
    h('span')
  )
, app)

No arrays, no useless flattening of a statically-known fragment, no key warnings. :)

from jsx.

taypo avatar taypo commented on May 5, 2024 6

I always felt the need for an xpath like object query language built in. Or may be a simpler expression language (eg. java uel, spring spel etc.).

from jsx.

sophiebits avatar sophiebits commented on May 5, 2024 6

@jmar777 To be clear, #35 would only change that example to have <button onClick=handleClick>text</button> with no braces, and you'd need explicit quotes when adding string text.

If people have more concerns about any particular issue, please comment on that issue's page instead of here.

from jsx.

xpagesbeast avatar xpagesbeast commented on May 5, 2024 6

JavaServer Faces (JSF) Expression language has stood the test of time, JSX is a very similar new kid on the block, here are some specs: https://docs.oracle.com/javaee/7/tutorial/jsf-el.htm. It would be nice to copy and paste between the two with minimal adjustments.

from jsx.

kemurphy avatar kemurphy commented on May 5, 2024 5

Fragments would be super useful. One way I've thought about going about it is using the spread operator in child context:

const frag = [
  <div />,
  <div />
];

return (
  <div>
    {...frag}
  </div>
);

One alternative could be using a self-closing tag instead of curlies for the spread (<...frag />).

Bonus points if sibling tags at the top level of the expression could implicitly create a fragment so we could avoid the trailing commas on the elements in the fragment array. This also adds support for multiple conditional children for free, since it's the same syntactic construct:

const frag = (
  <div />
  <div />
);

<div>
  { shouldShowChildren &&
    <div />
    <div />
    <div />
  }
</div>

from jsx.

OpakAlex avatar OpakAlex commented on May 5, 2024 5

Don't change anything. It works good, learn some machine learning, if you don't known where put your time. Or maybe just do world better, but please, don't change API :)

from jsx.

theduke avatar theduke commented on May 5, 2024 4

but would they be inserted in the DOM?

There should be a setting to turn it on for dev / off for production in the implementing libraries.

from jsx.

kevinSuttle avatar kevinSuttle commented on May 5, 2024 4

Funny you should ask: http://kevinsuttle.com/posts/jsx-2-adobe-flex

from jsx.

tracker1 avatar tracker1 commented on May 5, 2024 4

Most of these conditions could be handled with additional components/methods.

Possible solution for #4, add a raw() method on react-dom that returns a String object with a doNotEncode property... this can be checked for as part of the rendering path(s).

function raw(input) {
  const str = new String(input || '');
  str.doNotEncode = true;
  return str;
}

Then all you need to do is check for string object with said property and not html encode.... That would be additive and there shouldn't be any instances in the wild where this would break things.


Another is the desire for more conditional syntax, I'm against doing this via special props, and would rather see people either use ternary, the do expression default, or custom component wrappers for the purpose.

<If
  condition={ condition }
  then={ <component /> }
  else={ <component /> }
/>

function If(props) {
  const condition = props.condition || false;
  const positive = props['then'] || null;
  const negative = props['else'] || null;
  return condition ? positive : negative;
}

from jsx.

arendjr avatar arendjr commented on May 5, 2024 4

I think we should restrict any changes to JSX to ones that will not (or barely) impact existing codebases using JSX. This will also help people with large codebases (myself included) who'll have to migrate gradually to the next version, rather than convert everything overnight.

I don't like the argument of "you don't need to upgrade to JSX 2, you can keeping using the old version", because it creates friction in the community. It'll be harder to share components among projects that use different JSX versions, it creates ambiguity in online documentation/tutorials regarding the version they're using, and if you have to work across projects that involve different incompatible versions, it creates mental overhead and increases the chance of mistakes. To put it differently: I like ES6 because all ES5 is valid ES6 code. I will like JSX 2 if all JSX 1 code is also valid JSX 2 code.

So looking at the discussion above, I see definitely some features that I like:

  • Support for comments
  • Support for fragments
  • Computed attribute names
  • Optional curlies
  • Object short-hand notation

I'd say dropping HTML encoding is already tricky because it might break existing codebases, but its impact might be limited enough to be defensible. If an ESLint rule could be created for it (including a fixer, which should be doable) so that the issues can be spotted (and fixed) easily, I'd say it's not a deal breaker.

But I'd be strongly against #35 and also against the other proposals originally mentioned as controversial, for the reasons mentioned above.

from jsx.

sebmarkbage avatar sebmarkbage commented on May 5, 2024 4

Is it worth it to obsolete JSX tutorials currently out there and to have the community perform migrations and have people relearn the details of how JSX works, in order to have some syntactic sugar?

I'm not really sure. I think that most of these are not worth while on their own but maybe as a unit it might be worth while.

However, I've learned that it is not really up to me - or anyone else. If these things are considered valuable, then someone will build it and people will adopt it. In that case, the community will diverge and there will be things to learn anyway. I'm just trying to get out in front of it so that we can do it in a structured way instead of ad-hoc.

That said, I don't think anything in this issue means that this will actually happen. It is more about figuring out what it would be if we were to go down this route and getting feedback from the community so that we don't end up with disconnected ad-hoc forks.

from jsx.

oleksandr-shvets avatar oleksandr-shvets commented on May 5, 2024 3

@brochington you can do it in that way:

import myImageFunc as Img from "./somewhere"
     render() {
        return (
                <Img src={...}/> // compiled to myImageFunc
        )
    }

from jsx.

oleksandr-shvets avatar oleksandr-shvets commented on May 5, 2024 3

@brochington why myImageFunc is better than [Stateless Function Component](react pure functional components) for you?

from jsx.

oleksandr-shvets avatar oleksandr-shvets commented on May 5, 2024 3

@brochington you can do it using custom jsx pragma:
/** @jsx myImageFunc */

from jsx.

oztune avatar oztune commented on May 5, 2024 3

I really like the elegance and subtle benefits of #35.

I think the ability to mix JSX 1 and 2 in the same project will be a high priority for those of us maintaining large code bases.

from jsx.

rauchg avatar rauchg commented on May 5, 2024 3

@lacker I'm curious why you prefer that over do expressions? Seems a more elegant, "pure JS" solution

from jsx.

rauchg avatar rauchg commented on May 5, 2024 3

Obviously there's a quick declarative win (specially for analysis), but for most situations I think we just want a escape from the && hack and ? / :

from jsx.

arisAlexis avatar arisAlexis commented on May 5, 2024 3

I'd love to have conditionals so I don't have to write this.enabled && <div>

from jsx.

miraage avatar miraage commented on May 5, 2024 3

@mohsen1 I always separate same kind of logic into own method. IMO render() method should be simple and contain zero logic from first to last line of JSX = we see what is exactly returned.

class Foo extends Component {
  renderCTA() {
    const { isLoggedIn, onCTAClick } = this.props;

    if (isLoggedIn) {
      return (
        <button className="foo__cta" onClick={onCTAClick}>
          CTA!
        </button>
      );
    }

    return null;
  }

  render() {
    return (
      <div className="foo">
        {this.renderCTA()}
        <div className="foo__description">
          Lorem ipsum...
        </div>
      </div>
    );
  }
}

Same goes for stateless components - just use hoisting.

const Foo = ({ isLoggedIn, onCTAClick }) => {
  return (
    <div className="foo">
      {renderCTA()}
      <div className="foo__description">
        Lorem ipsum...
      </div>
    </div>
  );

  function renderCTA() {
    if (isLoggedIn) {
      return (
        <button className="foo__cta" onClick={onCTAClick}>
          CTA!
        </button>
      );
    }

    return null;
  }
};

from jsx.

SanderSpies avatar SanderSpies commented on May 5, 2024 3

I would prefer to remove:

  • #21 because it's as far as I know not possible within OCaml
  • #66 because it doesn't go well with the named arguments approach within Reason.

That said, I wonder if it's really a bad thing to diverge a bit. For example the JSX spread attributes are also not possible within Reason (well maybe with a lot of pain).

Also I would also like to add support for fragments, which @syranide already mentioned, and Reason already has.

from jsx.

klimashkin avatar klimashkin commented on May 5, 2024 3

#35 is the most anticipated feature since in our projects we don't have plain text in jsx anymore, only intl calls

from jsx.

tweeres04 avatar tweeres04 commented on May 5, 2024 3

@tomascharad You should just do

return (
    <div>
        Hi!
        {bool ? myComponent : null}
    </div>
);

from jsx.

mrberggg avatar mrberggg commented on May 5, 2024 3

I hope whatever changes are considered will prioritize simplicity, readability, an HTML-like syntax, and using plain old JavaScript. I think these are what make React so great.

from jsx.

fibo avatar fibo commented on May 5, 2024 3

Please add HTML style comments like this

<!--div>
  <MyComponent />
</div-->

from jsx.

mohsen1 avatar mohsen1 commented on May 5, 2024 2

@Pajn That looks much better than *if or anything like that. Also #35 is a great proposal! 👍

from jsx.

Pajn avatar Pajn commented on May 5, 2024 2

@brochington
Why not just write that as myImageFunc(class/string, props, ...children)? The point of JSX is basically to hide the repeated createElement call so if you want to call another function just once, write is as that. It would both be shorter and less surprising than a single tag that behaves differently from all the others.

from jsx.

jordwalke avatar jordwalke commented on May 5, 2024 2

@gaearon / @sebmarkbage I love a good bike-shed! :D

Please don't feel the need to incorporate all/any of Reason's JSX features/difference. Some of what we implemented, we did simply because:

  1. It was expedient.
  2. I requested that we try out a couple of features to see how they feel (for example, no {} around expressions that are already "simple" enough). I think I like it.
  3. Reason isn't just targeting web, but web and native compilation so embedding string text by default inside of <tag>here</tag> is less important, and maintaining compat with HTML is not as high of a priority. Therefore we were able to treat everything inside of tags as a space separated list of identifiers <tag>any list of componentIdentifiers here</tag> without needing interpolation {} (although interpolation is still valid if you want it because {x} is always equivalent to x in Reason!). Maybe we should reconsider this one though, so that people can copy/paste markup from the web into JSX more easily. How important is this?
  4. Because we know we can rapidly iterate without churning a bunch of developers. It's a laboratory where we can quickly refmt forward without breaking anyone since refmt is deeply integrated into Reason.

Frags seem like a nice addition though.

from jsx.

tomascharad avatar tomascharad commented on May 5, 2024 2

I haven't think about it thoroughly but I think it would be nice to have a way to conditionally render a component inside JSX 'html'.

I don't know if it would be better to have it as a Component's native prop (Which I believe it would be out of the scope of this thread):

<div>
  Hi!
  <MyComponent renderIf={bool} />
</div>

Or something more related to JSX sintax (haven't think about it thoroughly):

<div>
  Hi!
  {renderIf(bool) => <MyComponent />}
</div>

This would make my code much cleaner prior the return statement of the render function. I hate doing this kind of stuff:

  let myComponent = <div></div>;
  if(bool) {
    myComponent = <MyComponent />
  }
  return <div>
    Hi!
    {myComponent}
  </div>;

I think that reading the rendering if condition inside the HTML, is far more readable/maintainable.

from jsx.

arendjr avatar arendjr commented on May 5, 2024 2

@sebmarkbage Well, personally I tend to be a bit hesitant towards codemods. For one thing, if I were to convert 350 components overnight using a codemod, that would generate a Pull Request none of my team mates will be happy to review. It also creates noise in version control, making git blame for example less useful. Also, what guarantee do I have the code it generates will satisfy my ESLint rules? For me, a codemod should be a last resort rather than something I'd happily apply. I'd much prefer to keep the old code around for as long as it works.

But more specifically, if we're talking about #35, let's suppose I have the following snippet of code:

<div>
    <a onClick={this._like}>Like</a> &bull; <a onClick={this._comment}>Comment</a>
</div>

How will the codemod convert this code? Will it automatically wrap the " &bull; " part in a <span>? Currently there's no <span> there in the DOM, so needing one where it wasn't needed before could at least be seen as a slight regression.

from jsx.

arendjr avatar arendjr commented on May 5, 2024 2

Something more just came to mind: When you (as in: Facebook) released React v15, you published a blog post about the new versioning scheme: https://facebook.github.io/react/blog/2016/02/19/new-versioning-scheme.html

What I found very comforting back then was this quote:

Therefore, we're committed to making it easy for most components and libraries
built on top of React to be compatible with two major versions at the same time.
We will do this by introducing new APIs before completely removing the old ones,
thereby avoiding those cliffs.

This gives me a lot of confidence my projects built on React will be able to smoothly move forward without hitting a huge stumbling block where suddenly a lot of code has to be converted, because there will usually be a grace period during which code will work both in the old and the preferred new way.

Now while I understand the React API and the JSX syntax are strictly separate things, as a React-using developer I'd also argue JSX is a vital extension of the React API. After all, it's through JSX that I consume an important part of the React API. And as such I believe it would be a shame if the stability of the React API and its policy of avoiding sudden breaking changes were not respected similarly by JSX as well.

from jsx.

brochington avatar brochington commented on May 5, 2024 1

@alexander-shvets Your link doesn't seem to work for me, but I assume you are referring to This. The JSX still uses React.createElement. I would like to be able to control this.

from jsx.

chrisnankervis avatar chrisnankervis commented on May 5, 2024 1

I'd like to see a way to comfortably use deprecated HTML attributes. We're using JSX in an application that is used to build HTML emails; to avoid warnings we're prefixing the unsupported attributes with "data-", and then replacing them before send.

from jsx.

jpuri avatar jpuri commented on May 5, 2024 1

Nice changes proposed @sebmarkbage, it would be nicer to have JSX closer to JS then HTML.

from jsx.

holloway avatar holloway commented on May 5, 2024 1

While I'm generally wary of conditionals in JSX I do notice the syntactic complexity of React routers, and the hoops they have to jump through to lazy load components (in order to avoid components being instantiated immediately).

<Route path="/user" component={User}/>
<Route path="/task" component={Task}/>
<Route path="/task" component={Footer}/>
...

When a more natural syntax for any router would be,

<Route path="/user">
    <User andAnyArbitraryProps={here}/>
</Route>
<Route path="/task">
    <Task moreProps={here}/>
    <Footer/>
</Route>
...

But they can't do that because <User>, <Task>, and <Footer> are instantiated immediately, regardless of the route. Some routers can have hundreds of components, and it would be extremely inefficient to instantiate all those components and then only use one or two, so instead they typically use a component={User} approach with the router being responsible for instantiating the component itself, and of course each router has its own custom way of passing props. This all feels like a weakness of JSX.

Essentially what these routers probably need is delayed / lazy loading / optional execution of JSX functions.

One possible solution... JSX could support deferring the instantiation of components by wrapping them in a function. A parent component's this.props.children wouldn't be the instances themselves but would be a function that returns the instances. This means that JSX would need to support generating something like React.createElement( () => React.createElement(User) ) (compared to the existing React.createElement(User)). I'm guessing that this decision to allow lazy loading would be based on the parent component <Route> having a flag set, such as:

Route.deferChildren = true;

Then because the Route has opted-in to having lazy-loaded children it would have a render() that included {this.props.children()} (rather than {this.props.children}). This way it wouldn't require any coordination with React (I think), and it would just be a JSX change.

This would also happen to allow 3rd-party libraries to do conditionals by making an If component... eg, <If test={condition}><LazyLoadedChild/></If>.

Considering all it's doing is just wrapping props in an arrow function, then it might be useful to generalise it to all props:

Route.deferProps = ['children', 'someOtherCPUIntensiveProp']

A problem I see with this idea is that arrow functions are cheap but not free, and so rewrapping the components every time render() is called would waste memory. I guess caching and reusing these arrow functions (eg. cache them on the parent component) might be a good optimisation.

from jsx.

tweeres04 avatar tweeres04 commented on May 5, 2024 1

So then do

return (
    <div>
        Hi!
        {bool ? <MyComponent /> : null}
    </div>
);

My point is that it's already clean and simple to do what you're trying to do with jsx

from jsx.

syranide avatar syranide commented on May 5, 2024 1

@sebmarkbage Going off on a tangent, there's always the possibility of actually making it JSX1 vs JSX2 and simply requiring people to use both transformations if you want to keep old code around. Or if you will, JSXML vs JSX2 and officially keeping a JSX-version around that's tailored to HTML-style frontends, although that may also fracture the community.

But I feel like there is some merit to having a JSXML type of thing as JSX2 may be a bit cumbersome for small-scale purposes and not as friendly to the hobbyist crowd that JS has an excess of. So having JSXML as an introduction to React for hobbyist/small-scale apps and then JSX2 for when you generally intend to tackle business/larger problems. It would allow JSXML to make some trade-offs that aren't necessarily 100% technically sound, but which may appeal to that crowd. Just like jQuery is in many ways flawed, it's a perfect tool for those who are unfamiliar because it's simple and it works well enough. One could even imagine a ReactDOM-fork to go with it, with everything being compatible with HTML, lower-case props, non-document event listeners, non-pooled events, etc, but again, fracturing the community may be a problem.

That being said, I would probably never use JSXML myself, but it may be relevant for React to keep traction with newcomers and not seem like a frightening framework or one that it is exclusively for "large business needs".

from jsx.

fibo avatar fibo commented on May 5, 2024 1

support <!doctype>: this will make server side rendering a lot easier.

There are also a lot of other tags not supported, like <style>, <script>, etc.

if my jsx is like

<body>
  <h1>Hello JSX2</h1>
<body>

React should understand and mount it automatically, after body.... well this is brainstorimng, right?

from jsx.

alistairhutton avatar alistairhutton commented on May 5, 2024

Would be nice to have something like how Adobe/Apache Flex deals with conditional inclusion of components. It is refered to as state in Flex world. You can assign a child component a state name and then when you set the parent components state it hides/shows child components as appropriate

from jsx.

jasonslyvia avatar jasonslyvia commented on May 5, 2024

@syranide It would be better if it could be solved in syntax level.

from jsx.

BrendanFDMoore avatar BrendanFDMoore commented on May 5, 2024

@kevinsimper True, it's more compact. We stick to the other convention because instead of null we often want to show some placeholder text or replacement component.

@mohsen1 you're right, there's no harm in more helpful sugar to clean up unpleasant syntax where there is wide interest and a commonly accepted pattern. I'm not necessarily against the addition of an if helper.

from jsx.

NekR avatar NekR commented on May 5, 2024

Though, I'm not a fun of adopting features from Angular. Like some already here proposed are already possible with JSX + React.

from jsx.

brochington avatar brochington commented on May 5, 2024

@alexander-shvets Those aren't the same.

In my example img would compile to myImageFunc(class/string, props, ...children).
In your example Img would compile to React.createElement(Img, props, ...children).

from jsx.

brochington avatar brochington commented on May 5, 2024

@alexander-shvets That wouldn't work either, as both the <div /> and the <img /> would then use myImageFunc. Please notice the two arguments to my pragma definition above.

@Pajn JSX can and is used in other forms outside of the context of React. JSX is a way to define syntax sugar. In the case of React part of that sugar is hiding the createElement method. But their is no reason why this needs to be the case. Just as @alexander-shvets has pointed out, you can already define JSX compilation via pragma definitions. I just want a more granular approach to this.

from jsx.

caub avatar caub commented on May 5, 2024

you don't need to spread the 'fragment' array, React.createElement does it https://jsfiddle.net/crl/fsrny4jL/ (same in jsx)

from jsx.

oleksandr-shvets avatar oleksandr-shvets commented on May 5, 2024

@mstijak this feature was deprecated, but you still can turn on it, see https://github.com/RReverser/acorn-jsx:
jsx: { allowNamespacedObjects: true }
Or use dashes: <input type="text" value-bind="firstName">.

from jsx.

mstijak avatar mstijak commented on May 5, 2024

@alexander-shvets: I'm aware of the options. I like the dot syntax for attributes which require some kind of post-processing. Using namespaces for that purpose is convenient, but feels hacky.

from jsx.

ConAntonakos avatar ConAntonakos commented on May 5, 2024

Echoing @nkohari's concerns. I think trying to balance conditionality intermixed in JSX was my biggest struggle. My workaround was utilizing the do expression: http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions

from jsx.

jmar777 avatar jmar777 commented on May 5, 2024

Edit: I misunderstood something (see the following comment).

from jsx.

jmar777 avatar jmar777 commented on May 5, 2024

@spicyj 💡 doh! I did misunderstand the proposal. Thanks.

from jsx.

LucaColonnello avatar LucaColonnello commented on May 5, 2024

Nice to have something like https://www.npmjs.com/package/jsx-control-statements

from jsx.

klimashkin avatar klimashkin commented on May 5, 2024

@tweeres04
since bool sounds like boolean :)

return (
    <div>
        Hi!
        {bool && myComponent}
    </div>
);

from jsx.

tomascharad avatar tomascharad commented on May 5, 2024

Thanks @tweeres04, @klimashkin, That implies assigning the component in a variable.
What I'm suggesting is to try to avoid that assignation so the code doesn't get messy.

from jsx.

sebmarkbage avatar sebmarkbage commented on May 5, 2024

@arendjr Could expand a bit on why you wouldn't be able to convert overnight? E.g. with an automatic codemod. We can convert any caller automatically.

What are the problems you're expecting? This would be useful information.

from jsx.

sebmarkbage avatar sebmarkbage commented on May 5, 2024

@arendjr We generally assume that npm packages are published with their Babel extensions compiled out to a lowest common denominator. A lot of things break without that anyway. So any syntax changes wouldn't break already compiled packages upstream.

However, any breaking transition to new syntax would likely be using an opt-in header for a while so that you can keep having both in the same codebase at once, but that's a thing you wanted to avoid. I don't see any other way to make breaking changes other than doing them all at once - like codemods - or incrementally package by package or file by file. Not making breaking changes at all is way too restrictive with something like JSX at this stage. Just like many other Babel plugins like decorators, field initializers, classes etc. have all gone through breaking changes. If you're not willing to upgrade all at once or incrementally, I wouldn't recommend using non-standard syntax extensions at all.

Your example could be converted to this:

<div>
    <a onClick=(this._like)>"Like"</a>" \u2022 "<a onClick=(this._comment)>"Comment"</a>
</div>

Or if you're fine with unicode we can just put the " • " in your code.

There are no semantic differences needed. All the proposals are purely syntactic sugar.

from jsx.

arendjr avatar arendjr commented on May 5, 2024

@sebmarkbage Thanks for your detailed reply. Seems I was at least mistaken about #35, as I thought it implied having text nodes between other nodes was simply no longer possible. Glad that's not the case :)

What would such an opt-in header look like? Because if it does allow me to transition to a new version file by file, that would actually alleviate most of my personal complaints.

Regarding Babel plugins, I actually do stay away from experimental language extensions, exactly to avoid the risk of breaking changes. It's also why I have neither adopted Flow nor TypeScript, because I'd hate it to adopt a language extension only to find out a year later I bet on the wrong horse. Maybe I'm erring on the side of caution, but well, at least you know where I'm coming from :)

The thing is, I never thought of JSX as an experimental language feature. Non-standard, yes, but the React API is considered stable and it clearly advocates the use of JSX, which is why I had an expectancy of the same level of stability when I adopted JSX. Now when you say, "Not making breaking changes at all is way too restrictive with something like JSX at this stage." I think it makes it clear you're seeing it in a different light. That's not necessarily bad, I cannot judge that, but I've given my opinion which is that I think it might not be wise to introduce friction in the community at this point. And I think the reason I think it's unwise (but others might judge differently) boils down to how you answer the question: Is it worth it to obsolete JSX tutorials currently out there and to have the community perform migrations and have people relearn the details of how JSX works, in order to have some syntactic sugar?

from jsx.

fibo avatar fibo commented on May 5, 2024

It would be great to have more tools for indentation. On Codepen and vim, jsx indentation does not work.

from jsx.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.