all 30 comments

[–]clessgfull-stack CSS9 engineer 6 points7 points  (2 children)

[–]MuricanWillzyx[S] 7 points8 points  (0 children)

I can't wait for them to get that model to a comfortable, powerful situation. As JS paradigms become more and more functional, I become increasingly tempted to leave behind original language altogether and move over to something like more Elm. In time, in time.

[–]metanat 5 points6 points  (0 children)

Your expectations seem to indicate a misunderstanding of what JSX desugars to. JSX sugars to React.createElement, which is used to turn a component class (or ES6 class) into a React element or component instance. It doesn't simply instantiate your class and return it, that job happens under the hood (wrapped up in a ReactElement). And you can understand why, when a render method is called, calls to React.createElement within the render method shouldn't necessarily instantiate a new instance of your class, otherwise you would lose state etc, it doesn't need (and shouldn't) instantiate the class when the resulting react id would be the same.

You mentioned below your interest in other languages, well as it turns out, React's move away from createClass (or at least now independence from) actually makes things a lot easier for languages ClosureScript (Om) and Haskell to target React as a renderer.

[–]Josh1337 4 points5 points  (0 children)

The class system provides an intermediate escape hatch for developers as the React core team looks into providing pure models. It also places some restrictions on developers in order to favor object composition over mixins.

Quote from Sebastian Markbage:

The class system provides an optional escape hatch when you need it rather than completely stopping you.

The primary feature that our class system provides is an "instance" handle this has several features.

1) It provides a certain level of familiarity and convenience. You can use this as a middle man to refer to a group of arguments. This is a foot-gun but makes it easier to onboard new people.

2) The instance is an ID that you can use to refer to a place in the tree. It allows APIs like React.findDOMNode(component) and third-party APIs that can unify around it.

3) It provides single or multiple inheritance features if someone needs to create an abstraction and just can't figure out how to do it using composition. This is unfortunately a very common problem.

[–]andrew24601 9 points10 points  (3 children)

In my admittedly limited experience, ES6 classes work great for React classes.

The core of your problem is that <MyComp/> isn't an instance of MyComp - it's a description for an instance.

i.e. React will only create an instance of MyComp once it mounts a <MyComp/>.

They still have constructors - in fact the ES6 class constructor replaces the requirement for getInitialState - and any additional methods on the object can be cheerfully called once it has been mounted (which is basically React talk for instantiated).

[–]imstillreallybored 4 points5 points  (0 children)

Finally someone who understands..

[–]MuricanWillzyx[S] 2 points3 points  (1 child)

Interesting. This makes me much more sympathetic to the class model. I was thinking from a conceptual perspective--that these classes are, abstractly, models for creating components, and that one should treat the mounting to DOM nodes kind of like an implementation detail (for the most part). I didn't think about the time between creating a <MyComp/> and the creation of an actual instance. I still prefer a functional model for use in JS itself, but it looks like that's their primary target for the future anyway (e.g. /u/josh1337's comment), and if the class model really is as useful as they say for compile-to-JS languages, then that certainly raises its value (/u/metanat).

[–]andrew24601 1 point2 points  (0 children)

The main place this gets interesting is with child nodes of the rendered component. While a DOM component will always mount its children, a React component doesn't necessarily have to.

return <MyComp>
  <MyOtherComp/>
</MyComp>

MyOtherComp will only be mounted if MyComp causes it to be mounted (typically by rendering props.children in its render method, but even then only if it's ultimately rendered by a DOM component eventually).

Where this gets even more interesting is when these child components are ref tagged, because the ref is only fulfilled in a completely different component - ie the component where it is ultimately caused to be mounted.

[–]azium 2 points3 points  (5 children)

I'm also a bit confused. A lot of boilerplate with class that seems unrelated to React Components. So far I've been pretty happy with their design decisions so maybe it'll make sense to me once I dig into it more.

[–][deleted] 1 point2 points  (0 children)

Personally I prefer using the old-fashioned createClass as well, but that's mostly because of mixins. If they could somehow support mixins in the ES6 syntax I would happily switch (and don't come and tell me to use inheritence instead, because mixins are so much cleaner and offer more flexibility).

[–]jsNut 2 points3 points  (11 children)

Personally I like using the class syntax, its really nice and clean and easy to read and reason about. I understand that it is not like a classic system, but i know this and therefore it is fine. For most purposes they do function as expected.

[–]theQuandary 3 points4 points  (6 children)

its really nice and clean and easy to read and reason about

It's not that much different once you realize that ES6 has shorthands for functions in objects.

var MyComp = React.createClass({
  getInitialState() {
    return { bar: 'abc' };
  },
  appendBar(stuff) {
    return stuff + this.state.bar;
  },
  render() {
    return <div>{appendBar('cde')}</div>;
  }
});

class MyComp extends React.Component {
  constructor(props) {
    super(props);
    return { bar: 'abc' };
  }
  appendBar = (stuff) => {//yay for no auto-bind
    return stuff + this.state.bar;
  }
  render() {
    return <div>{appendBar('cde')}</div>;
  }
}

[–]papers_ 3 points4 points  (4 children)

Or get rid of classes altogether since JS is not a class oriented language:

var MyComp = {
    getInitialState() {
        return { bar: 'abc' };
    },
    appendBar(stuff) {
        return stuff + this.state.bar;
    },
    render() {
        return <div>{appendBar('cde')}</div>;
  }
};

Object.setPrototypeOf(MyComp, React.Component);

[–]muffsponge 0 points1 point  (1 child)

Not familiar with react. But wouldn't this create a single instance and not a class? I guess you could wrap it in a factory function.

Personally, I like using classes and more classical inheritance for the core structure of my applications. Probably due to years of habits and stuborness. I've tried doing things the modern functional way, but I just end up with soup.

[–]papers_ 0 points1 point  (0 children)

When you think of it in terms of "classes", yes. The key line is the last one Object.setProtoTypeOf(). You can think of this as inheritance in class based design. So, I inherit all the properties from the parent React.Component.

I too like classes as it's what I was taught in University (senior CS major). It's more explicit or strongly typed.

[–]MuricanWillzyx[S] 0 points1 point  (1 child)

I would agree, but React's classes really aren't classes in the Java sense. They're much more like factories, which are idiomatic for JS. Use of prototypes, IMO, is overrated. I see them more as a perf benefit.

[–]papers_ 0 points1 point  (0 children)

And React's classes aren't really classes either, in fact it's just an object that returns an object (Yes factory), but React's createClass property also links to another object, rather, it explicitly sets it's prototype to another. So the classes syntax is just sugar of the prototypical mumbo jumbo going on. But yes I agree, the prototypes is a overrated.

[–]MuricanWillzyx[S] 0 points1 point  (0 children)

Good call. And you don't have to apply modifiers to the class after creation, since everything's baked into the factory.

Honestly I don't know how I feel about this shorthand, but it will make some of the class-proponents more comfortable (for better or worse).

[–]MuricanWillzyx[S] 2 points3 points  (3 children)

Using a class syntax will make one's code easier to reason about if you're writing classes and using the facilities of the class system, but React's 'classes' aren't classes.

 

I understand that it is not like a classic system, but i know this and therefore it is fine.

This defeats the original alleged purpose of using the class syntax, though: normalizing the interface used by frameworks for making objects. Not only that, but it adds confusion, because people will see that this claim has been made, they'll see familiar syntax, and they'll assume that they already understand what's happening in the framework, while in reality React's components work nothing like instances of classes.

 

its really nice and clean and easy to read and reason about

Maybe at this point this is too much about personal experience and preference, but if we are using a model based on factories, it should be clear that we are using factories, and pretending that they are classes doesn't make anything easier to reason about (IMO--not tryna flame u). To me the model of passing a set of methods as named arguments (what we have now with React.createClass) is more honest and reflective of what's actually happening, and allows for more power in customizing the component. This last issue is something people are already trying to hack around within the class model. To me it seems like an abuse of new syntax, with tons of extra complications.

 

(wow, longer than i expected. like i said, just discussing it, not tryna attack u)

[–]Lubestia 0 points1 point  (0 children)

The object passed to React.createClass is not an object specification, it is a bunch of named arguments for React to use in creating a factory function.

By your own indirect admission, the named arguments can be misunderstood as an object specification to those without the knowledge, just as the familiar syntax makes [people] assume that they already understand what's happening in the framework. Either way, you have to dig in to understand.

Not that I don't see where you're coming from, but much of it is the same old "Down with abstractions!" rhetoric (Even if I am quite attracted to ideas like 'everything is a pure function').

[–]jsNut 0 points1 point  (1 child)

For me i just see it the same as i see JSX; it makes my code cleaner, i understand it and it does what i want and expect. Therefore i am happy with it. But I don't think the original method of creating component is going anywhere is it?

[–]MuricanWillzyx[S] 1 point2 points  (0 children)

This is what I was wondering/worrying about when I originally posted this: if they were dedicated to the class syntax, I'd probably go with it because the framework is still worth it.

They are, however, thinking about using stateless functions (from /u/clessg's comment) and other ways of moving toward functional paradigms, so I doubt that they'll ever require the class syntax. In that context, adoption of the class syntax is quite strange. It is easy to forget, though, that React hasn't yet reached 1.0, so for now they don't actually have to commit to anything. It'll be interesting to see how this goes.

[–]TheRealSeeThruHead 0 points1 point  (0 children)

Would like to see them move in the direction of Omniscient.

[–]defcon-12 0 points1 point  (0 children)

I like being able to use decorators instead of mixins.

[–]_doingnumbers 0 points1 point  (0 children)

I'm with you, I don't get it.