skip to Main Content

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


  1. 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:

    import React from "react"
    import { useIntl, Link, FormattedMessage } from "gatsby-plugin-intl"
    
    const RootIndex = (props) => { 
     const intl = useIntl();
      return (
        <Layout>
          <SEO
            title={intl.formatMessage({ id: "title" })}
          />
    ...
    

    You are missing the const intl = useIntl(); that allows your code to use the gatsby-plugin-intl internationalization. Instead of passing it through props, once you import it, you need to instance it above the return statement.

    Login or Signup to reply.
  2. Same problem trying adding location and crumbLabel variables in Layout.js

    Adding

    this.state = {
            location: props.location,
            crumbLabel: props.crumbLabel,
        };
    

    and

    const { location } = this.state;
    const { crumbLabel } = this.state;
    

    works form me.

    Example code:

    src/pages/index.js

    import React from 'react';
    import Layout from '../components/Layout';
    
    const IndexPage = ({location}) => (
      <Layout location={location} crumbLabel="Home">
        ...
      </Layout>
    );
    
    export default IndexPage;
    

    src/components/Layout.js

    import React, { Component } from 'react';
    import { Breadcrumb } from 'gatsby-plugin-breadcrumb'; 
    
    class Layout extends Component {
     constructor(props) {
        super(props);
        this.state = {
            location: props.location,
            crumbLabel: props.crumbLabel,
        };
      }
    
      render() {
        const { location } = this.state;
        const { crumbLabel } = this.state;
        return (
      
          <Breadcrumb location={location} crumbLabel={crumbLabel} /> 
         
        );
      }
    }
    export default Layout;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search