Artur Woźniak

Frontend Developer

Jul 01, 2020 in Quick Tips

'Seek first to understand, then to be understood' is one of my life principles. I was more than happy to find my motto in Codetain’s work politics, as well. We’re systematically arranging knowledge sharing sessions...

Quick Tips: how to render components conditional?

Hello again! I like to keep my promises — that is why in this quick tip, I will present a way to render different components when you click/chose a specific option from navigation.

Just like before (<— Quick Tips: using forwardRef to measure element height dynamically), I will use and extend our previous example to demonstrate a different content for a different view (Home, About, Contact).
We will modify only the App component.

The first step — create required components

Home component

import React, { useState } from "react";
import ActiveClass from "../ActiveClass";

const textData = [
  {
    id: 1,
    text: "Yes! I'm active 💪"
  },
  {
    id: 2,
    text: "My turn now 🤠"
  },
  {
    id: 3,
    text: "Thanks for activating 😘"
  }
];

const Home = () => {
  const [activeId, setActiveId] = useState(null);

  const handleClick = id => () => {
    const activeElement = textData.find(item => item.id === id);

    activeElement && setActiveId(id);
    console.log(activeElement.id);
  };

  return (
    <div>
      <h2>Hello from Home.jsx</h2>
      <ActiveClass
        data={textData}
        onClick={handleClick}
        activeId={activeId} />
    </div>
  );
};

export default Home;

It holds the logic for the active class component from my first quick tip (<— Quick Tips: add and remove active style).

ActiveClass component

import React from "react";

const activeStyle = {
  background: "hotpink",
  color: "white"
};

const ActiveClass = ({ data, onClick, activeId }) => {
  return data.map(({ id, text }) => {
    return (
      <p
        style={id === activeId ? activeStyle : {}}
        key={id}
        onClick={onClick(id)}
      >
        {id === activeId ? text : "Activate me, please"}
      </p>
    );
  });
};

export default ActiveClass;

About component

import React from 'react';

const About = ()=> {
  return <h2>Hello from About.jsx</h2>
}

export default About;

Contact component

import React from 'react';

const Contact = ()=> {
  return <h2>Hello from Contact.jsx</h2>
}

export default Contact;

The second step — add function with the switch statement

const pageContent = () => {
    switch (activeNavOption) {
      case "home":
        return <Home />;
        break;
      case "about":
        return <About />;
        break;
      case "contact":
        return <Contact />;
        break;
      default:
        return;
    }
  };

This will allow us to render a different component base on ‘activeNavOption’  state.

The third step — call pageContent function in the main tag

<main>{pageContent()}</main>

I had replaced <p>Hello! I’m in container under fixed navigation</p> with <main>{pageContent()}</main>.
And that is it, you can render components base on a chosen navigation option.

App component

import React, { useEffect, useState, useRef, useCallback } from "react";
import { render } from "react-dom";
import Hello from "./components/Hello";
import Navigation from "./components/Navigation";
import { About, Contact, Home } from "./components/pages";
import "./style.css";

const App = () => {
  const [activeNavOption, setActiveNavOption] = useState("home");
  const [navigationHeight, setNavigationHeight] = useState(undefined);
  const navigation = React.createRef();

  useEffect(() => {
    setNavigationHeight(navigation.current.offsetHeight);
  }, []);

  const pageContent = () => {
    switch (activeNavOption) {
      case "home":
        return <Home />;
        break;
      case "about":
        return <About />;
        break;
      case "contact":
        return <Contact />;
        break;
      default:
        return;
    }
  };

  const handleNavOptionClick = useCallback(
    event => {
      console.log('I was called');
      const navOptionName = event.target.getAttribute("data-name");
      setActiveNavOption(navOptionName);
  },
  [activeNavOption]
  );

  return (
    <>
      <Navigation
        ref={navigation}
        currentOption={activeNavOption}
        handleNavOptionClick={handleNavOptionClick}
      />
      <div style={{ marginTop: `${navigationHeight + 20}px` }}>
        <main>{pageContent()}</main>
      </div>
    </>
  );
};

render(<App />, document.getElementById("root"));

Small inclusion.
Normally, when building applications with navigation we would use React Router to accomplish rendering of different components based on routes, but this tip gives you the skill to do that for components not related to browser URL.

Back to top