1

I just watched a talk from React Conf 2018. In the video, the speaker shows 2 ways to set the document title. The first is by using the Lifecycle methods (componentDidMount and componentDidUpdate) if we use a class component, the second one is by using the useEffect hook if we use a function component. It looks like that's the recommended way to do it according to answers from this question.

But, I tested the following code and it seems to work just fine to set the document title directly:

import React from 'react';
import ReactDOM from 'react-dom';

function App() {
    document.title = 'wow'
    return <p>Hello</p>
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
)

The title changed:
screenshot

Is there any significance of setting the document title inside useEffect or componentDidMount?
Or is it because it was the only way to set the document title?
Is it okay to set the document title directly like I did in the snippet above?

Update:

It also works with class component:

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {
    render() {
        document.title = 'wow'
        return <p>Hello</p>
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
)
M Imam Pratama
  • 998
  • 11
  • 26
  • 1
    While I don't feel like this is the best question for Stack Overflow. I have also asked the same question... It works in the render, why do I need the useEffect? I haven't found a great explanation for this anywhere. – Corey Gibson Jun 29 '21 at 16:54

2 Answers2

2

Use react-helment which is also widely used in other frameworks with the same name as helmet express ...

Here is the same code:

import {Helmet} from "react-helmet";

class Application extends React.Component {
  render () {
    return (
        <div className="application">
            <Helmet>
                <meta charSet="utf-8" />
                <title>My Title</title>
                <link rel="canonical" href="http://example.org/example" />
            </Helmet>
            ...
        </div>
    );
  }
};

Another way to use via props to which is cleaner IMO

...
<Helmet titleTemplate={`%s | ${props.title}`} defaultTitle={constants.defaultTitle} />

You may also use react-helmet-async for more features.

Lalit Yadav
  • 889
  • 9
  • 16
2

The thing is, the render function in React, is considered to be a pure function.

A pure function should not have any side-effects. Eventually updating the document.title means that you are referencing the document directly from render-> which is already considered a side effect.

Render should mainly do one thing -> render some JSX, if there is a need to do some API calls/interact with the document/window etc..., this should be placed in componentDidMount/componentDidUpate for a class Component, OR in a useEffect/useLayoutEfect for a functional component based on hooks.

(useEffect for e.g. is a function that runs asynchronously, and updating the document title from it will not block the rendering, whereas doing it directly will block it.)