2

want to update the title present in the Header everytime we navigate to a new page. Is passing the _setTitle method with the props the way to go?

import React, { Component } from 'react';
import PropTypes from 'prop-types';

Main App component

export class App extends Component {
  constructor() {
    super();

    this.state = { pageTitle: 'My app' };
    this._setTitle = this._setTitle.bind(this);
  }

  _setTitle(title) {
    this.setState({ pageTitle: title });
  }

  render() {
    const { pageTitle } = this.state.pageTitle;

    return (
      <div>
        <Header title={pageTitle} />
        {React.cloneElement(children, { setTitle: this._setTitle })}
        <Footer />
      </div>
    );
  }
}

Header and Footer Components

export class Header extends Component {
  static propTypes = {
    title: PropTypes.string
  };
  // ...
  render() {
    const { title } = this.props;

    return <h2>{title}</h2>;
  }
}


export class Footer extends Component {
  // Footer code
}

Following are the different page Components:

export class Profile extends Component {
  static propTypes = {
    setTitle: PropTypes.func.isRequired
  };
  componentWillMount() {
    this.props.setTitle('Profile');
  }
}


export class Projects extends Component {
  static propTypes = {
    setTitle: PropTypes.func.isRequired
  };
  componentWillMount() {
    this.props.setTitle('Projects');
  }
  // ...
}


export class ProjectForm extends Component {
  static propTypes = {
    setTitle: PropTypes.func.isRequired
  };
  componentWillMount() {
    this.props.setTitle('New Project');
  }
  // ...
}


export class Translators extends Component {
  static propTypes = {
    setTitle: PropTypes.func.isRequired
  };
  componentWillMount() {
    this.props.setTitle('Translators');
  }
  // ...
}

// ...

How can I improve upon this. I'm new to react so pls suggest If you have any ideas, I'll implement it. Thank you.

Amin Mozhgani
  • 606
  • 1
  • 7
  • 21
Akash Sawant
  • 657
  • 1
  • 5
  • 11

1 Answers1

0

You can make use of Context and pass the setTitle method as a Context value, then you can create a Component that has the logic of setting the Title, A simple implementation would look like

const TitleContext = React.createContext();

export class App extends Component {
  constructor() {
    super();

    this.state = { pageTitle: 'My app' };
    this._setTitle = this._setTitle.bind(this);
  }

  _setTitle(title) {
    this.setState({ pageTitle: title });
  }

  render() {
    const { pageTitle } = this.state.pageTitle;

    return (
      <TitleContext.Provider value={{setTitle: this._setTitle}}
        <div>
          <Header title={pageTitle} />
          {this.props.children}
          <Footer />
        </div>
     </TitleContext.Provider>
    );
  }
}

class TitleSetter extends React.Component {
    static propTypes = {
        title: PropTypes.string.isRequired
    }
    componentDidMount() {
        this.context.setTitle(this.props.title)
    }
}

TitleSetter.contextTypes = TitleContext;

Now in any component you can simply render the TitleSetter like

export class Profile extends Component {
  render() {
    return (
        <div>
              <TitleSetter title="Profile" />
              {/* other context */}
        </div>
    )
  }
}

Also while looking into context, please look at the this question on how to access context outside of render

Shubham Khatri
  • 211,155
  • 45
  • 305
  • 318