This is not a comprehensive list, just a few things I was thinking about and wanted to write down for newcomers.
If you're interested in doing deep-dive workshops that take you from beginner to fairly advanced material, checkout our public workshops at https://reacttraining.com/public-workshops/
React has been around for almost 8 years which is getting up there as far as JS libraries and frameworks that stay popular. It might seem like there's a bunch of "churn" in React but most of it has been community based and not the library itself. In other words, it was super popular to use [some state manager] library with React and now maybe that library is less popular because there are other (perhaps better) choices. Maybe someone likes Sass or CSS modules and someone does CSS-in-JS libraries. Again, these are things that fall into community churn but not React itself.
Let's start with the version numbers of React before we dig into other stuff. At the time of this writing, React 18 is on the horizon. But does that mean there have been 18 major version numbers of React? Not so much.
When I got started in React around 2015 it was on version 0.12 and they hadn't released their first major version. The community was already calling that version 12 though probably because React had been out for a few years and all they had were minor versions. Similarly, React 0.14 was dubbed "React 14" by the community. When the React team was ready for their first major release, they thought it might be confusing if they called it v1 because many people who were new thought it was already on 14. In hindsight I wish they called it v1 and just dealt with that small confusion. But instead they decided to call the first major version of React v15 to try and alleviate the confusion. I guess now newcomers think there have been 18 versions of React so the confusion is there no matter what.
In reality, React has done a great job of not changing too much over its first three major versions (15, 16, and 17). The most notable changes were probably the refactor of class lifecycle methods when they renamed some of them and then the classes to hooks change. But even the classes to hooks was just a minor change (16.8) and not a major breaking change. One could have a class-based project on 16.0 and update to 16.8 without any breaking changes and then slowly migrate to hooks if they want to. We can even make the argument that this is unnecessary to refactor since some would consider their legacy projects good enough with classes and maybe they'll explore hooks in future projects.
Let's get into the main topic, the things that are old practices or syntax that aren't prevalent or necessary anymore.
.js
or .jsx
files
You don't need to do .jsx
files anymore. It used to be that code editors weren't caught up with syntax-highlighting for JSX and needed a separate extension to get the syntax-highlighting to work. I can't speak for every code editor, but syntax-highlighting for JSX in VSCode works just fine with .js
files (and has for a number of years)
PropTypes
This one depends on whether you're using TypeScript or similar tools like Flow. Without those tools, you'd create a propTypes
property on your component. Here is one for a functional component:
function MyComp = () => {
}
MyComp.propTypes = {/* types here */}
Then you would use the PropTypes
object to describe your props. The PropTypes
object used to be apart of the core React library but they took it out and now you have to npm install
it separately.
Default Props
Similar to Prop Types, you can do this:
function MyComp = ({ number }) => {
// number will be 0 if the owner component didn't pass a number prop in.
}
MyComp.defaultProps = { number: 0 }
This isn't necessary anymore because you can do a default value for your prop in the destructure itself:
function MyComp = ({ number = 0 }) => {
// number will be 0 if the owner component didn't pass a number prop in.
}
The React team has even told developers that defaultProps
will be deprecated someday.
Memoized and Pure Components
If you want a component to not re-render when its owner (parent) component gets a re-render, you can convert to one of two things with a class-based component:
class MyComp extends React.Component {
/* conditionally return true or false if you want the render method to be called*/
shouldComponentUpdate(nextProps) {}
}
or
class MyComp extends React.PureComponent {
}
You can either use shouldComponentUpdate
to individually decide on a prop-by-prop basis if there are no changes and you want to skip re-rendering. Or you can extend PureComponent
which basically does the same as shouldComponentUpdate
but automatically for you for all props. In general we don't use classes much anymore if we're embracing hooks though so I consider both of these to be kind of old. I just wanted to bring them up to show the equivalent way for a function component:
const MyComp = React.memo(() => {
// This function passed into React.memo will now be "memoized"
})
This is the same as doing a class-based PureComponent
Setting State
In class-based components, the way state was batched could lead to you having some application bugs if you had some circumstances along with "setting state from state":
this.setState({ count: this.state.count + 1 })
So it was encouraged to do the other state setting API which was to pass a function into setState
when you set state from state:
this.setState((state) => state.count + 1)
If you're using hooks today, maybe you did or didn't know that the state setting functions also have two API's -- one for passing your new state as the argument and one that resembles the older setState(fn)
API.
setCount(count + 1)
setCount(count => count + 1)
Just know that the "setting state from state" batching issue of classes doesn't really exist anymore with function components and hooks so there's much fewer reasons to use the setCount(fn)
API. The reasons I've used it are fairly advanced so we won't go over them here, but chances are you won't need it often.
So may ways to make a component!
At any given point in time in React's history, there have been only two ways to make a component. The first API back in 2013 was React.createClass
and that was the only way to make a component. You'll never ever need that today unless you app is legacy from 2015. After that syntax the React team came out with real JS classes (because they were only just created for JavaScript in 2015). Then the React team came out with the functional component so starting around 2017 (I think it was) and up until today, you could do either one of these: a class or a function and those are the only two ways:
class MyComp extends React.Component {} // or
function MyComp() {}
I think some people might get more confused about the fact that JavaScript lets you make functions a few different ways so technically that functional component can be written as any of these:
function MyComp() {}
const MyComp = function() {}
const MyComp = () => {}
This isn't really "different ways" to make a component, they're all just valid functions and that's what React needs so sometimes it comes down to developer preference. There's technically a difference between these as far as JS is concerned, but those differences don't present themselves too often when we write React so it usually doesn't matter.
For a while, the community was calling the functional components "Stateless Functional Components" but we stopped doing that when they started to have state with things like hooks.
So we still just have two ways of making components
class MyComp extends React.Component {} // or
function MyComp() {} // with alternative function syntax
Some have said that there's other ways to make components like memoized components and higher order components. That's not exactly true.
A memoized component (which we showed earlier in this post) is when we simply pass a function component into the React.memo()
API and they will wrap your component in another component to "memoize" it and prevent re-renders on your component when props haven't changed. It's not exactly a "another way" to make components as much as it's just a feature of them. The same is true for class-based and PureComponent
.
Higher Order Components (HoC) are a pattern where you pass a component into a function that helps you to make an abstraction for your component. It was an awkward community-driven pattern that many React developers would even say is an anti-pattern at this point. "HoC" is not apart of the React API, it's just a pattern for class-based components that we don't need anymore because of hooks. So this isn't a "type of" component and you probably don't need to learn the pattern at all unless you're doing class-based components.
But the documentation...
The React documentation still has a lot of their docs written for class-based components because over the last two years most companies have been transitioning to hooks and it didn't make sense to get rid of the old docs as soon as hooks came out. Right now the React team is re-writing the documentation to be more about hooks and less about classes (which are still technically supported but the community considers to be legacy). Because of the older importance of HoC's with classes, there's still a documentation page for them. But again this is old and is also not "a type of component".
Hopefully this clears some things up. I might add to this as I think of things. Feel free to ask any syntax questions in the comments.
As stated before, if you're interested in doing deep-dive workshops that take you from beginner to fairly advanced material, checkout our public workshops at https://reacttraining.com/public-workshops/
Top comments (0)