Categories
React Tips

React Tips — Scroll to Top When Navigating

Spread the love

React is a popular library for creating web apps and mobile apps.

In this article, we’ll look at some tips for writing better React apps.

Return Multiple Lines JSX in Another Return Statement in React

We can return multiple lines of JSX code in when we map them from an array by returning an array in the map callback.

For instance, we can write:

render() {
  return (
    {[1, 2, 3].map((n) => {
      return [
        <h3>Item {n}</h3>
        <p>{n}</p>
      ]
    }}
  );
}

We can also return a fragment to wrap around the components:

render() {
  return (
    {[1, 2, 3].map((n, index) => {
      return (
        <React.Fragment key={index}>
          <h3>Item {n}</h3>
          <p>{n}</p>
        </React.Fragment>
      )
    }}
  );
}

Get History on react-router

We can get the history with React Royer by calling the createBrowserHistory method.

For instance, we can write:

import { Router } from 'react-router-dom'
import { createBrowserHistory } from 'history'
import App from './App'

const history = createBrowserHistory({
  //...
});

ReactDOM.render((
  <Router history={history}>
    <App />
  </Router>
), holder)

We can also use the withRouter higher-order component to inject the history object into a component.

For instance, we can write:

import { withRouter } from 'react-router-dom';

class App extends React.Component {
  render () {
    this.props.history;
  }
}

withRouter(App);

We called withRouter with App to inject the history prop to it.

Then in our App component, we can get the history with this.props.history .

Include a Font Awesome Icon in React’s render()

To include Font Awesome icons in our React app, we can install the package by running:

npm install --save font-awesome

Then we can include the bundled CSS by writing:

import '../node_modules/font-awesome/css/font-awesome.min.css';

or:

import 'font-awesome/css/font-awesome.min.css';

And then in our component, we write:

render() {
    return <div><i className="fa fa-spinner fa-spin"></i></div>;
}

We set the class names for the icon as the value of the className prop.

There’s also the react-fontawesome package that lets us use icons by including the them bundled React components in our components.

To install it, we run:

npm install --save react-fontawesome

Then we import it by adding:

const FontAwesome = require('react-fontawesome');

Then we can use it by writing:

class App extends React.Component {
  render() {
    return (
      <FontAwesome
        name='rocket'
        size='2x'
        spin
        style={{ textShadow: '0 1px 0 rgba(0, 0, 0, 0.1)' }}
      />
    );
  }
});

We use the FontAwesome component to add the icon.

React Router Scroll to Top on Every Transition

We can create our own component to scroll to the top and wrap that around the component that we want to scroll to the top.

For instance, we can write:

class ScrollToTop extends Component {
  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      window.scrollTo(0, 0)
    }
  }

  render() {
    return this.props.children
  }
}

export default withRouter(ScrollToTop)

We call the withRouter prop with the ScrollToTop component.

Then we have the location prop available in ScrollToTop after that.

In the component, we check the location prop to see what the path is in the componentDidUpdate method.

If they’re different, that means we transitioned to a new route.

So we call window.scrollTo(0, 0) to scroll to the top of the page.

In render , we render the children prop so that we display the content of it.

Then, to use it, we write:

import ScrollToTop from './ScrollToTop';

//...

const App = () => (
  <Router>
    <ScrollToTop>
      <Foo />
    </ScrollToTop>
  </Router>
)

We wrap it our around Foo component to scroll it to the top when it’s loaded.

Also, we can do the same thing with hooks.

For instance, we can write:

import { useEffect } from 'react';
import { withRouter } from 'react-router-dom';

function ScrollToTop({ history }) {
  useEffect(() => {
    const unlisten = history.listen(() => {
      window.scrollTo(0, 0);
    });
    return () => {
      unlisten();
    }
  }, []);

  return null;
}

export default withRouter(ScrollToTop);

We use withRouter again so that we get the history prop.

But we call history.listen instead of checking the value of history .

We call window.scrollTo(0, 0) whenever the callback of history.listen runs.

It returns a function to remove the listen.

So we put that into the function that’s returned in the useEffect callback.

We pass in an empty array as the 2nd argument of useEffect to only load the callback when the component mounts.

Then we use it by writing:

<Router>
  <>
    <ScrollToTop />
    <Switch>
        <Route path="/" exact component={Home} />
    </Switch>
  </>
</Router>

Conclusion

There are several ways to scroll to the top when we navigate to a different route.

We can return multiple components with map in an array.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *