I recently started using Gatsby and am having some troubles understanding some of the concepts (that might actually come from React).
For example: I am using a plugin for I18n called gatsby-plugin-intl and I am struggling to understand how I can fit the code from the documentation into my code.
My code I got from a starter package containts a file with code like this at src/pages/index.js
:
import React from "react";
class RootIndex extends React.Component {
render() {
return (
...
But very often, I encounter code examples that start like this:
import React from "react"
const RootIndex = () => {
return (
...
Apparently, both approaches produce the same output.
But when I am confronted with a tutorial telling me to implement code like this:
import React from "react"
import { injectIntl, Link, FormattedMessage } from "gatsby-plugin-intl"
const RootIndex = ({ intl }) => {
return (
<Layout>
<SEO
title={intl.formatMessage({ id: "title" })}
/>
...
I have no idea where to put the argument intl
using the first approach defining a class. This does not work
import React from "react";
import { injectIntl, Link, FormattedMessage } from "gatsby-plugin-intl"
class RootIndex extends React.Component {
render({ intl }) {
return (
<Layout>
<SEO
title={intl.formatMessage({ id: "title" })}
/>
...
I hope that my description and issue is clear. I am missing knowledge to be more concise here.
Which would be the right way to go?
2
Answers
They are exactly the same in terms of output but not in terms of performance and what they are. They are called stateful (class-based component) and stateless components (functional component).
Generally, if you only want to render a component, I would suggest a functional component since it has better performance and makes the code clear and more reusable, allowing you to atomize better the functionalities.
On the other hand, if you are using some programming pattern (BLoC, MVVM, etc) you may need to create classes to hold the business logic, what allows you to extend from each other.
Class-based component (Stateful)
Class-based components make use of ES6 class and extend the Component class in React.
Sometimes called "smart" or "stateful" components as they tend to implement logic and state.
React lifecycle methods can be used inside class components (
componentDidUpdate
,componentDidMount
, etc).You pass props down to class components and access them with
this.props
(this
keyword).You need to bind/unbind events and functions.
Functional component (Stateless)
Functional components are basic JavaScript functions. These are typically arrow functions but can also be created with the regular
function
keyword.Contrary to the class-based component, these ones sometimes referred to as "dumb" or "stateless" components as they simply accept data and display them in some form; that is they are mainly responsible for rendering UI.
React lifecycle methods (for example,
componentDidMount
) cannot be used in functional components. However, they allow you to use React Hooks (useState
,useEffect
, etc) which handles all the typical lifecycle benefits adding a cleaner, and reusable code.There is no render method used in functional components, the return of the function will handle it. Therefore, they mainly responsible for UI.
Functional components can accept and use props.
They have slightly better performance than class-based ones. But the most important thing in my opinion is that they are cleaner and much more reusable.
References:
Regarding your implementation, since
gatsby-plugin-intl
uses internal hooks (useIntl
) the following code should work:You are missing the
const intl = useIntl();
that allows your code to use thegatsby-plugin-intl
internationalization. Instead of passing it throughprops
, once you import it, you need to instance it above thereturn
statement.Same problem trying adding
location
andcrumbLabel
variables in Layout.jsAdding
and
works form me.
Example code:
src/pages/index.js
src/components/Layout.js