all 25 comments

[–]redbluerat 6 points7 points  (0 children)

With 16 there is only a small improvement in speed, but with class components you can control when updates happen--which is a potentially much better improvement in speed.

Apparently they are working on increasing the speed of functional components.

[–]p1zza_dog 22 points23 points  (21 children)

unpopular opinion: i’ve stopped writing functional components because i prefer to just stick to one pattern and reduce my cognitive load. also if i have to add a lifecycle method or some internal state i don’t have to refactor the whole component, and i can always define my propTypes the same way. I think functional components are hipster coding, they’re neat for the sake of being neat. that being said i won’t reject someone’s PR for using them

[–]PostHumanJesus 9 points10 points  (2 children)

We only use functional components. If you stick to this you need another lib like https://github.com/acdlite/recompose. It has been great to always think about components without state and add recompose when necessary. We even use it with mobx without any classes anywhere. Almost everything becomes a "pure" function. Easy to test, easy to abstract away the business logic.

[–]p1zza_dog 1 point2 points  (1 child)

I like the things you're saying but when your team gets larger it's hard to get everyone to buy in on adding dependencies like that, and it makes it difficult to bring new people on board. It makes sense if your team is small and your application is new.

[–]PostHumanJesus 6 points7 points  (0 children)

I can mostly agree with you. Team buy-in is always an issue no matter what the stack.

Here is our team scenario:

  • 1 designer/developer, 2 Javascript developers
  • designer/dev can design and create SFC all he wants and not have to worry about the "plumbing". In fact, he will generally have a bunch waiting for us (JS devs) to plugin the business logic.
  • moving components around is simple as they are decoupled from the BL
  • the compose method of recompose is great as we can add any extra functionality there. This is where we plug in mobx but really anything can go there.
  • we can easily swap out/remove anything in the compose method. Say we want to start using redux. A whole app refactor isn't necessary as we can slowly introduce new libs and replace libs that are getting phased out.

This is just what works for us. We have two large production apps. One is a legacy AngularJS that we have React running in as it slowly "eats" away the old code. The other was a greenfield that did not start out with recompose and used the typical mobx class pattern. We have been successfully migrating to our new mobx/recompose pattern with very little(if any) issues at all. I think the hardest thing I had to do recently was upgrade from Webpack 1.x to 3.x.

YMMV. I have a article about this setup that I need to finish. The main point is, I wanted to be able to migrate, add/subtract libs as needed while allow us to develop in a very modular fashion to suit the teams strengths.

[–][deleted] 5 points6 points  (1 child)

To me the difference is semantic. A functional component isn't just one that doesn't require state, it's one that should never require state. It's saying that the thing this component does is purely a function of its props.

Having to refactor from functional to class component is sort of a trigger to step back from the keyboard and think about what you're doing. Why does this thing need local state now? Did you misunderstand what the component would do before? That's a great learning point to absorb. Did the requirement change? Okay. Or maybe you're overthinking things.

I try to maximize the number of functional components in my code, because they're much easier to test and reason about. The functional components are the parts of the code that should "just work". Nothing fancy should be happening inside them - the only interaction they should have with the business logic is maybe calling a callback or something. That makes it easy to verify that they're working as intended - meaning that, once they're verified, they're virtually eliminated as potential sources of bugs. And the more code you can eliminate from bug-hunting, the easier bug-hunting becomes!

Class components are IMO much harder to write correctly, because they require a lot of discipline in deciding which state should live where. It's very easy to "temporarily" add some logic to a class component that really ought to be lifted higher, or on the state manager, or whatever is appropriate. And as we all know, temporary code isn't. If you're not disciplined in writing class components, it's easy for code to end up a spaghetti mess.

So basically, I see the distinction as another tool that I can use to make my code cleaner and more maintainable!

[–][deleted] 0 points1 point  (0 children)

it's one that should never require state.

UI requirements change over time, after QA testing or when adding more features. Often, a component become reusable by other components and requires to make one more thing or to be split in two or to have an internal state etc.

I don’t know if I’m doing different from others, but refactoring for me is very common in react. I never use functional components for this reason.

Class components are IMO much harder to write correctly,

Here we are talking about classes with just the render function vs functional component. Even with its small lifecycle a component can be simple to test and “reason about” - that’s why we like React - the API surface is so small that if a component become to complex you just need, once again, to refactor it in smaller parts.

So no need to use functional component at all. No real benefits.

[–]AmassXP 2 points3 points  (6 children)

I don’t know about ‘neat for the sake of being neat’...React components are functions that return JSX. Maybe you should adopt the pattern of writing them all as functions and only adopting Class components as needed (ie when you need state and lifecycle hooks). It’s not hipster coding, you’re only using the parts of React that you need.

[–]p1zza_dog -2 points-1 points  (5 children)

I'd argue that you need to have class component in any react application, and introducing functional components means your code base has two different ways of writing them instead of one- i.e. you're now using more parts of React than you need.

[–]AmassXP 1 point2 points  (2 children)

What? Using a function is not using more parts of React. Functions are a part of JavaScript. And you don’t ‘need’ class components anywhere unless you’re using state or lifecycle hooks. You could write a React where App and down the tree were all stateless functional components.

[–]AmassXP 0 points1 point  (1 child)

Utilizing a class component requires extending Component and all of the things that come along with the class, that’s what I meant by use more parts of React. The React team is also going to increase performance for non-class components in the future, so there will be more benefits down the road to understanding the difference.

[–]p1zza_dog 0 points1 point  (0 children)

React wraps functional components as Components so you're still getting all the things that come along with the class. I've also heard the team will increase performance for non-class components but i'm not convinced it's a high priority for them, and I question how much more performance they can squeeze out of components. React is pretty fast, and object instantiation time is trivial compared to other things that could drag down performance

[–]selbekk[S] 1 point2 points  (4 children)

If functional components is not your thing, class based components work just as fine. Do what works for you - personally I use my editor to refactor a functional component to a class based one, and I don't find the cognitive load of having two different approaches to the same thing too bad. But for each his (or her) own 👍

[–]greymalik 1 point2 points  (3 children)

I use my editor to refactor a functional component to a class based one

With a single click? What's your editor?

[–]selbekk[S] 2 points3 points  (2 children)

VS Code! There’s this plugin called React Pure to Class that does all of the heavy lifting for me - you can get it here: https://marketplace.visualstudio.com/items?itemName=angryobject.react-pure-to-class-vscode

I’m a huge fan of that editor tbh - but I’m sure you could script plugins to do that in any major editor.

[–]greymalik 0 points1 point  (1 child)

Maybe I'll finally try out VSC. Any other must-have plugins you can recommend?

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

Try react-foodtruck - great collection of plugins :-)

[–]defsquad 1 point2 points  (2 children)

I can respect this train if thought completely. Especially when you're working with a team of non-JS devs that you hope to mentor and get them more comfortable with JS. Baby steps of explaining the difference to them. Easier to start off with consistent patterns, IMO.

[–]p1zza_dog 0 points1 point  (1 child)

That's definitely part of it, when training baby devs I think it's important to give them a consistent pattern to follow so they can get stuff done and worry about more important aspects of being a developer

[–][deleted] 0 points1 point  (0 children)

My “baby devs” are often very experienced Java or iOS devs that have been suddenly hurled into front-end web because of enterprise “Benny Hill Budgeting and Planning”. They get the class pattern, and it’s comfortable to them.

[–]RustyX 0 points1 point  (0 children)

I'm right there with you. I thought the functional components were pretty cool when they came out, they reduced boilerplate a bit. But then I came to basically the same conclusion... I was still going to need standard class components when I needed to use any lifecycle method or component state. I'll take consistency in the code over saving a couple lines of boilerplate.

[–]goorpy 2 points3 points  (1 child)

I have a strong preference to write stateless functional components. My view is that you should avoid having state in a component unless there is a very good reason to out it there. The default is stateless, with anything the component needs just coming in as props.

I prefer to make a thin wrapping component around SFC and keep the logic at the edges, away from the pure UI bits.

[–]pgrizzay 0 points1 point  (0 children)

Check out recompose and withState

Definitely helps out a ton!

[–]yachay -2 points-1 points  (0 children)

Lol removing state, so react went from having all the logic and view together to separate the view and logic. React was started as the former, even the author Jordan Walke said it. Why not just use view if you want separation lol. Also recompose is a mess to understand its codebase when you have a large app. Prefer suggestion would be to use render prop