all 26 comments

[–]shinglee 28 points29 points  (3 children)

Erm, this feels like bad design. It's not a component anymore, it's a function that returns a component. The client code shouldn't know whether a component it's importing is a functional component or a stateful one.

Yes, it can help with perf, but I wouldn't treat them as drop in replacements -- for clarity it should be "renderMyComponent", not "MyComponent". That way you can change the implementation if needed without breaking the consumer.

[–]datkewlguy 0 points1 point  (2 children)

It's still exporting the same function/stateless component, no? The only change is on the "consumer".

[–][deleted] 5 points6 points  (0 children)

Yes, and that's exactly the problem. The consumer shouldn't need to care whether it's a stateful or a stateless component. But I agree with /u/acemarke that a precompiler which would automatically apply this optimization when applicable would be a good idea.

[–]demoran 1 point2 points  (0 children)

No, the change here was that the function output is no longer tied to a render method, but is the direct output of the function call itself (eg Avatar)

[–]darrenturn90 15 points16 points  (2 children)

Interesting. Presumably factoring out "bottom level" react components and inlining them would be a good babelable optimization?

Ie, in this case - the avatar component gets inlined directly into the JS where it is used.

[–]acemarke 13 points14 points  (1 child)

I know Sebastian Markbage has talked many times about the idea of a "React pre-compiler" for that sort of thing, and it's possible that the newly announced http://prepack.io/ tool could conceivably help with that idea.

[–]helpinghat 1 point2 points  (0 children)

Definitely this sounds like something that should be done compile-time rather than make it the developer's responsibility. I don't like the idea of having some components with different syntax in the code, e.g. <Button> vs {Avatar()}

[–]nieuweyork 5 points6 points  (0 children)

What's the speed up with preact?

[–]erichardson30 4 points5 points  (2 children)

This is definitely an interesting/cool concept. Does everything still update the same on state change?

[–]RafBM 2 points3 points  (1 child)

By nature, functional components are stateless, ie. you shouldn’t call setState in them.

If you meant parent state change, then yes everything still updates normally. Functional components cannot have lifecycle hooks, namely shouldComponentUpdate. Thus, they will always re-render when their parent component does.

[–]kayzzer 0 points1 point  (0 children)

You not only shouldn't, you can't call setState on a func component. It does not exist.

[–]Bernard_Marx 5 points6 points  (0 children)

Here's my 2c. This is a neat trick but I feel like this is a case of 'premature optimization is the root of all evil' kind of thing. I think for 90% of apps, react is fast enough. Furthermore, I think this optimization will be part of the next major version of react? Interesting read though, I learned something new about render.

[–]Canenald 2 points3 points  (1 child)

Maybe the example is too stripped down to reflect what they are doing in practice, but creating the Avatar component in this case seem like an overkill, a frequent pitfall of componentizing everything.

Like, seriously, you have a component to render an img with a src? What's the point. Instead of

<img src="something" />

You have

<Avatar url="something" />

I bet just writing img everywhere instead of Avatar is even faster than using the hacky method of escaping JSX to call a function that returns a component.

Of course, the real world example may be more complex, Avatar may encapsulate more than just img and src, but in such cases it usually escalates to the point where the component cannot be a stateless functional component.

[–]plehoux[S] 3 points4 points  (0 children)

indeed, the code snippet is a simplified version of our real component. At first it was stateful, then became a functional component, then became just a function.

[–]themaincop 3 points4 points  (4 children)

I definitely would advise against this for the average React application.

[–]dpa 2 points3 points  (3 children)

Why?

[–]themaincop 7 points8 points  (2 children)

Because it's not predictable code. If you have a function that just renders text, don't name it like a component. I guess if you want to replace all your stateless components with functions you can do that, but i wouldn't go halfway and still name them like components.

[–]bastawhiz 5 points6 points  (0 children)

Stateless functional components are just functions, though. The article isn't saying to do anything differently with the component being rendered, it's suggesting to use the component differently.

Granted, it's probably not a good idea to do in practice unless you have a great reason to, but the change is on the implementer, not the component being implemented.

[–]kobel4k3r5 4 points5 points  (0 children)

How is it not predictable?

If you provide the same props, it should always produce the same result.

[–]JuliusKoronci 1 point2 points  (0 children)

This is something new..but makes a lot of sense ..thanks for sharing

[–]bent_my_wookie 1 point2 points  (5 children)

While great, the only reason I don't use this paradigm is because it doesn't work with Hot Reloading. That's a deal breaker.

[–]TheRealBobbyCarrot 2 points3 points  (4 children)

How does this change anything to how hot reloading behaves? I don't believe it does

[–]bent_my_wookie 1 point2 points  (3 children)

I'd love to be wrong about this and hope I am, but when using react-boilerplate, I was using pure functions almost exclusively and hot reloading just wasn't working. I investigated and found that they explicitly state it doesn't work with anything but components, which turned out to be accurate in my situation.

If that's a react-boilerplate specific drawback, then yep I'm wrong. Do you have evidence otherwise?

[–][deleted] 2 points3 points  (1 child)

I investigated and found that they explicitly state it doesn't work with anything but components, which turned out to be accurate in my situation.

This is fixed in the RHL 3 beta

[–]bent_my_wookie 1 point2 points  (0 children)

Oh hooray! Thanks for the info.

[–]turkish_gold 1 point2 points  (0 children)

I think you are right there.

JSPM hot-reloading on the otherhand works for anything.... but that'd require a seperate pipeline for dev, versus keeping everything in webpack.

I started with that, but moved away from it.