Build a React Responsive Navigation Menu with React Hooks and Sass

Build a React Responsive Navigation Menu with React Hooks and Sass

In this video tutorial, we will learn how to build a responsive navbar with React, Reach Router, and Sass.

What Is Responsive Web Design?

Responsive Web design is the approach that suggests that design and development should respond to the user’s behavior and environment based on screen size, platform and orientation.

The practice consists of a mix of flexible grids and layouts, images and an intelligent use of CSS media queries. As the user switches from their laptop to iPad, the website should automatically switch to accommodate for resolution, image size and scripting abilities. One may also have to consider the settings on their devices; if they have a VPN for iOS on their iPad, for example, the website should not block the user’s access to the page. In other words, the website should have the technology to automatically respond to the user’s preferences. This would eliminate the need for a different design and development phase for each new gadget on the market.

Download and Run

git clone https://github.com/syntacticsolutions/react-navigation-menu.git
cd react-navigation-menu

In the project directory, you can run:

npm start

Runs the app in the development mode.

Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.

You will also see any lint errors in the console.

npm test

Launches the test runner in the interactive watch mode.

See the section about running tests for more information.

npm run build

Builds the app for production to the build folder.

It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.

Your app is ready to be deployed!

See the section about deployment for more information.

npm run eject

Note: this is a one-way operation. Once you eject, you can’t go back!

If you aren’t satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.

Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.

You don’t have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.

Learn More

You can learn more in the Create React App documentation.

To learn React, check out the React documentation.

Code Splitting

This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting

Analyzing the Bundle Size

This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size

Making a Progressive Web App

This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app

Advanced Configuration

This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration

Deployment

This section has moved here: https://facebook.github.io/create-react-app/docs/deployment

npm run build fails to minify

This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify

React Tutorial | Build a Simple CRUD App with ReactJS

React Tutorial | Build a Simple CRUD App with ReactJS

Learn ReactJS with this tutorial! React for both beginners

How to implement Carousel in React app using React Responsive Carousel

How to implement Carousel in React app using React Responsive Carousel

In this React Responsive Carousel tutorial. we will learn how to implement Carousel in a React app using React Responsive Carousel package. React 16+ Responsive Carousel tutorial with examples. The carousel tutorial with React. Carousels are commonly used on the front of the applications, there are various ways through which we can implement Carousels in React, but In this tutorial, we will take the help of React responsive carousel package.

This is a step by step React Responsive Carousel tutorial. In this tutorial, we will learn how to implement Carousel in a React app using React Responsive Carousel package.

Carousels are commonly used on the front of the applications to show image galleries, sell products, show related blogs, show repetitive related content and to grab the attention of new visitors on the web or mobile application.

There are various ways through which we can implement Carousels in React, but In this tutorial, we will take the help of React responsive carousel package.

Table of Contents

  1. Setting Up React App
  2. Creating React Component
  3. Installing React Responsive Carousel Package
  4. Adding Responsive Carousel in React
  5. Adding Infinite Loop, Keyboard Control and Auto Play
  6. Carousel Methods
  7. Conclusion
1. Setting Up React App

To implement carousel in React app, run the following command to install new React project.

npx create-react-app react-responsive-carousel

Get inside the React project.

cd react-responsive-carousel

Next, start the React app.

npm start
2. Creating React Component

Create a new folder, name it components and also create a new file inside the src folder and name it carousel.component.js.

Add the following code inside of it.

import React from "react";

export default function CarouselComponent() {
    return (
        <div>
            <h3>Carousel in React</h3>
        </div>
    );
}

Register the CarouselComponent in App.js.

import React from 'react';
import './App.css';
import CarouselComponent from "./components/carousel.component";

function App() {
  return (
    <div className="App">
      <CarouselComponent />
    </div>
  );
}

export default App;
3. Installing React Responsive Carousel Package

In this step, we will install the React Responsive Carousel package using the NPM command.

npm install react-responsive-carousel --save
4. Adding Responsive Carousel in React

To run the carousel, open the public folder and add some images inside of it.

To initialize the Carousel in React we need to open the carousel.component.js component file and import the Carousel from ‘react-responsive-carousel’ package.

import { Carousel } from 'react-responsive-carousel';

Next, import the carousel css in the Carousel component file.

import "react-responsive-carousel/lib/styles/carousel.min.css";

Next, add the Carousel HTML code inside the CarouselComponent class.

export default function CarouselComponent() {
    return (
        <div class="carousel-wrapper">
            <Carousel>
                <div>
                    <img src="../img-01.jpg" />
                </div>
                <div>
                    <img src="../img-02.jpg" />
                </div>
                <div>
                    <img src="../img-03.jpg" />
                </div>
            </Carousel>
        </div>
    );
}

We have implemented a simple Carousel in React app. This is a simple image slider, It contains small thumbnails on the bottom which also works like a navigation button.

Clicking on the bullet points and small thumbnails we will navigate to the clicked image, and this will be displayed on the Carousel screen.

This carousel contains the next and previous buttons, which helps in navigating back and forth.

5. Adding Infinite Loop, Keyboard Control and Auto Play

In this step we will add Keyboard control, Infinite Loop and Auto play feature in React Carousel.

Infinite Loop: This feature allows Carousel to run even after you reach to the last image slide.

Keyboard Control: Navigate to previous and next screen using Keyboard back and forward keys.

Auto Play: Slider starts running automatically, without touching the next and previous keys.

Add the infiniteLoop, useKeyboardArrows and autoPlay directive in the <span><</span>Carousel<span>></span> tag to initiate the above features.

import React from "react";
import "react-responsive-carousel/lib/styles/carousel.min.css";
import { Carousel } from 'react-responsive-carousel';

export default function CarouselComponent() {
    return (
        <div class="carousel-wrapper">
            <Carousel infiniteLoop useKeyboardArrows autoPlay>
                <div>
                    <img src="../img-01.jpg" />
                </div>
                <div>
                    <img src="../img-02.jpg" />
                </div>
                <div>
                    <img src="../img-03.jpg" />
                </div>
            </Carousel>
        </div>
    );
}
6. Carousel Methods

Managing the Carousel behavior is easy in React, The React Responsive Carousel plugin offers tons of features to customize the carousel.

showArrows: Default value set to true, displays previous and next arrows.

showStatus: Default value set to true, displays current item’s index.

showIndicators: Default value set to true, displays small dots below the with links to change the items in the Carousel.

showThumbs: Default value set to true, shows images for the thumbnails.

thumbWidth: Default value is undefined, optionally specify pixel width of a thumbnail to avoid calculating values.

infiniteLoop: Adds infinite loop in carousel, default value set to false.

selectedItem: Declares the starting selected item.

axis: Converts the orientation horizontal or vertical, default value is horizontal.

onChange: Triggered when updating the positions.

onClickItem: Triggered when an item is clicked.

onClickThumb: Triggered when a thumbnail is clicked.

stopOnHover: Default value set to true, Stops auto play when mouse is over the carousel.

interval: Default value set to 3000, Adds time interval in auto play.

transitionTime: Default value set to 350, Time interval in milliseconds between slide transition.

swipeable: Default is set to true, allows swiping gestures.

dynamicHeight: Default is set to false, manages the carousel height if needed. It does not work with vertical axis.

centerMode: Default is set to false, allows centered view with partial previous and next slides. It only works with horizontal axis.

labels: Optionally specify labels to be added to controls.

onSwipeStart: Triggered when a swiping gesture has initialized.

onSwipeEnd: Triggered when a swiping gesture has completed.

onSwipeMove: Triggered when a swiping gesture is happening.

You can also check out the full documentation of Carousel plugin here.

7. Conclusion

We have completed the carousel tutorial with React, I hope you loved this tutorial and share with others. You can download the full code of this tutorial on this GitHub repo.

How to Create a Modal Route with React Router

How to Create a Modal Route with React Router

Building a modal module for react with react-router. First, go ahead and install react-router-dom through npm. At the very top level of your application,

Modals are very useful for displaying one view on top of another.

However, they are more than an absolutely positioned <div> element wrapping everything when it comes to implementation. Especially if you need dynamic URLs, page refreshes, or a simple scrolling interaction on a mobile device.

In this article, we’ll discuss the various aspects of modals and identify solutions to satisfy the requirements that come with creating dynamic URLs, page refreshes, and other features.

Before starting to shape the modal component, let’s start with some basics of the react-router package.

We’ll use four components from this package: BrowserRouter, Route, Link, and Switch.

Since this is not a react-router tutorial, I won’t be explaining what each of these components do.

However, if you’d like some info about react-router, you can check out this page.

Basic routing

First, go ahead and install react-router-dom through npm.

npm install react-router-dom --save

At the very top level of your application, use the <BrowserRouter/> component to wrap your app.

import { BrowserRouter } from "react-router-dom";

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

Inside <App/>, you’ll need to specify the routes so that you can render a specific view when one of them — or none of them — match.

Let’s assume we have three different components to render: <Home/>, <About/> and <Contact/>. We’ll create a navigation menu, which will always be visible at the very top of the application.

The <Link/> or <NavLink/> components from react-router-dom are used for navigation purposes, while <NavLink/> has the special feature of being applicable to a specific styling when the current URL matches.

Functionality-wise, you can use either one.

Below is the basic structure of the navigation menu, which changes the URL accordingly:

render() {
  return (
    <div className="app">
      <div className="menu">
        <Link className="link" to='/'>Home</Link>
        <Link className="link" to='/about'>About</Link>
        <Link className="link" to='/contact'>Contact</Link>
      </div>
    </div>
  );
}

The next thing we’ll do is implement the mechanism that matches the URL and renders a specific component.

<Switch/> renders the first matching location specified by its <Route/> children. When nothing is matched, the last <Route/> is returned — usually as a 404 page.

render() {
  return (
    <div className="app">
      <div className="menu">
        <Link className="link" to='/'>Home</Link>
        <Link className="link" to='/about'>About</Link>
        <Link className="link" to='/contact'>Contact</Link>
      </div>
      <Switch>
        <Route exact path="/" component={Home} />
        <Route exact path="/contact/" component={Contact} />
        <Route exact path="/about" component={About} />
        <Route>{'404'}</Route>
      </Switch>
    </div>
  );
}

Creating a modal component

So far, we’ve implemented the basic routing structure. Now we can create a modal component and work on displaying it as an overlay.

Although there are a variety of different methods for creating modal components, we’ll only be covering one.

A modal component has a wrapper element which spans the whole screen — width and height.

This area also acts as a clickedOutside detector. Then the actual modal element is positioned relative to that wrapper element.

Below is an example of a <Modal/> functional component using withRouter HOC (Higher order component) to access the router history and call the goBack() method to change the application URL when the modal is closed on click to .modal-wrapper.

onClick={e => e.stopPropagation()} is used to prevent propagation of the click event and trigger the onClick on .modal-wrapper, which would close the modal when the actual .modal element is activated.

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

const Modal = () => (
  <div
    role="button"
    className="modal-wrapper"
    onClick={() => this.props.history.goBack()}
  >
    <div
      role="button"
      className="modal"
      onClick={e => e.stopPropagation()}
    >
      <p>
        CONTENT
      </p>
    </div>
  </div>
);

export default withRouter(Modal);

Styling the .modal-wrapper is just as important. Below, you can find the basic styling used to make it span the whole screen and appear above the content.

Using -webkit-overflow-scrolling: touch enables elastic scroll on iOS devices.

.modal-wrapper {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100vh;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
}

Opening the modal view

The modal component we created should render on top of the existing view when a specific URL is matched, meaning that somehow we have to change the URL so the routing mechanism can decide what to render.

We know that <Switch/> renders the first matching location, but a modal overlay needs two <Route/> components rendering at the same time.

This can be achieved by putting the modal <Route/> out of <Switch/> and rendering it conditionally.

In this case, we should be able to detect if a modal is active or not.

The easiest way to do this is by passing a state variable along with a <Link/> component.

In the same way we used the <Link/> component to create the navigation menu, we’ll use it to trigger a modal view.

The usage shown below lets us define a state variable, which is then made available in the location prop, which we can access within any component using withRouter HOC.

<Link
  to={{
    pathname: '/modal/1',
    state: { modal: true }
  }}
>
  Open Modal
</Link>

Put this anywhere you want. Clicking the link will change the URL to /modal/1.

There might be several modals with different names like modal/1, modal/2, and so on.

In this case, you’re not expected to define each <Route/> intended to match the individual modal locations. In order to handle all of them under the /modal route, use the following syntax:

<Route exact path="/modal/:id">

This gives you the flexibility of getting the value of the hardcoded :id parameter within the modal component through the match.params prop.

It also lets you do dynamic content renderings, depending on which modal is open.

Matching the modal location

This section is particularly important because it identifies the mechanism for displaying a modal on top of an existing view even though the location parameter changes when a modal is opened.

When we click the Open Modal link defined in the previous section, it will change the location path to /modal/1, which matches nothing in <Switch/>.

So we have to define the following <Route/> somewhere.

<Route exact path="/modal/:id" component={Modal} />

We want to display the <Modal/> component as an overlay.

However, putting it inside <Switch/> would match it and only render the <Modal/> component. As a result, there would be no overlay.

To resolve this problem, we need to define it both inside and outside of <Switch/> with extra conditions.


Below, you’ll see the modified version of the same snippet. There are several changes. Let’s list them quickly:

  • There is a previousLocation variable defined in the constructor.

  • There is an isModal variable defined, which depends on some other values.

  • <Switch/> is using a _location_ prop.

  • There are two <Route exact_path_="/modal/:id" component={Modal} /> used both inside and outside <Switch/>, and the one outside is conditionally rendered.

When a modal is opened, we need to store the previous location object and pass this to <Switch/> instead of letting it use the current location object by default.

This basically tricks <Switch/> into thinking it’s still on the previous location — for example / — even though the location changes to /modal/1 after the modal is opened.

This can be achieved by setting the location prop on <Switch/>.

The following snippet replaces the previousLocation with the current location object when there is no open modal.

When you open a modal, it doesn’t modify the previousLocation.

As a result, we can pass it to <Switch/> to make it think we’re still on the same location, even though we changed the location by opening a modal.

We know that when a modal is opened, the state variable named modal in the location object will be set to true.

We can check if the state of the location object is defined and has the state variable of modal set to true.

However, these two checks alone do not suffice in the case of refreshing the page.

While the modal has to be closed on its own, location.state && location.state.modal still holds.

Checking whether this.previousLocation !== location, we can make sure that refreshing the page will not result in setting isModal to true.

When the modal route is visited directly, which is modal/1 in our example, then none of the checks are true.

Now we can use this boolean value to both render the <Route/> outside of the <Switch/>, and to decide which location object to pass to location prop of <Switch/>.

Given that <Modal/> component has the necessary stylings, this results in two different views rendering on top of each other.

constructor(props){
  super(props);
  this.previousLocation = this.props.location;
}

componentWillUpdate() {
  const { location } = this.props;
  if (!(location.state && location.state.modal)) {
    this.previousLocation = this.props.location;
  }
}  

render() {
  const { location } = this.props;
  const isModal = (
    location.state &&
    location.state.modal &&
    this.previousLocation !== location
  );

  return (
    <div className="app">
      <div className="menu">
        <Link className="link" to='/'>Home</Link>
        <Link className="link" to='/about'>About</Link>
        <Link className="link" to='/contact'>Contact</Link>
      </div>
      <Switch location={isModal ? this.previousLocation : location}>
        <Route exact path="/" component={Home} />
        <Route exact path="/contact/" component={Contact} />
        <Route exact path="/about" component={About} />
        <Route exact path="/modal/:id" component={Modal} />
        <Route>{'no match'}</Route>
      </Switch>
      {isModal
        ? <Route exact path="/modal/:id" component={Modal} />
        : null
      }
    </div>
  );
}

Rendering different modal views

So far we have implemented our modal in a way that ensures we don’t render an overlay when refreshing a page with an open modal, or when directly visiting a modal route.

Instead, we only render the matching <Route/> inside <Switch/>.

In this case, the styling you want to apply is likely to be different, or you might want to show a different content.

This is pretty easy to achieve by passing the isModal variable as a prop on the <Modal/> component, as shown below.

Then, depending on the value of the prop, you can apply different stylings or return a completely different markup.

return (
  <div className="app">
    <div className="menu">
      <Link className="link" to='/'>Home</Link>
      <Link className="link" to='/about'>About</Link>
      <Link className="link" to='/contact'>Contact</Link>
    </div>
    <Switch location={isModal ? this.previousLocation : location}>
      <Route exact path="/" component={Home} />
      <Route exact path="/contact/" component={Contact} />
      <Route exact path="/about" component={About} />
      <Route exact path="/modal/:id" component={Modal} />
      <Route>{'no match'}</Route>
    </Switch>
    {isModal
      ? <Route exact path="/modal/:id">
          <Modal isModal />
        </Route>
      : null
    }
  </div>
);

Preventing the scroll underneath the modal

When you open the modal on some browsers it may have the content below scrolling underneath the modal, which is not a desirable interaction.

Using overflow: hidden on body is the first attempt to block scrolling on the entire page.

However, although this method works fine on desktop, it fails on mobile Safari since it basically ignores overflow: hidden on body.

There are several different npm packages attempting to remedy this scroll locking issue virtually across all platforms.

I found the body-scroll-lock package quite useful.

From this package, you can import disableBodyScroll and enableBodyScroll functions, which accept a reference to the element for which you want scrolling to persist as an input.

When the modal is open we want to disable scrolling for the entire page, except for the modal itself.

Therefore, we need to call disableBodyScroll and enableBodyScroll functions when the modal component is mounted and unmounted, respectively.

To get a reference to the parent <div> of the modal component, we can use the createRef API from React and pass it as a ref to the parent <div>.

The code snippet below disables scrolling when the modal is open and enables it again when the modal component is about to be unmounted.

Using this.modalRef as the input for these imported functions prevents the content of the modal component from being scroll-locked.

Before using the disableBodyScroll function, we need a simple check.

This is because a modal component might get mounted if the page is refreshed when a modal is open, or when the modal route is visited directly.

In both cases, scrolling should not be disabled.

We have already passed the isModal variable as a prop to the <Modal/> component to render different views, so we can just use this prop to check if there is actually a modal.

Below is the modified version of the modal component:

import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';

class Modal extends Component {
  constructor(props) {
    super(props);
    this.modalRef = React.createRef();
  }
  
  componentDidMount() {
    const { isModal } = this.props;

    if (isModal) {
      disableBodyScroll(this.modalRef.current);
    }
  }
  
  componentWillUnmount() {
    enableBodyScroll(this.modalRef.current);
  }
  
  render() {
    return (
      <div
        ref={this.modalRef}
        className="modal-wrapper"
        onClick={() => this.props.history.goBack()}
      >
        <div
          className="modal"
          onClick={e => e.stopPropagation()}
        >
        </div>
      </div>
    )
  }
}

Conclusion

You now have an understanding of how a modal view works, as well as a sense of some of the problems you may encounter while implementing your own integration.

For the fully functional example, visit this code sandbox project.