Search code examples
reactjsnode.jsreact-hooksreact-routerstyled-components

In this Sidebar, buttons don't load the correct content page I want. But rather does nothing. I can't find out why. Help appreciated


Here are the related components I used to build the Sidebar UI. Everything is displaying fine. But the loading of the content pages and how to connect the Content.jsx and SideNavBar.jsx to display perfectly is pretty much troublesome.

1. SideBarButton.jsx - this is used for the buttons of Sidebar

import React from "react";
import styled from "styled-components";
import { colors } from "../../assets/colorPalette"; // Assuming you have a file for colors

const SideBarButton = ({ onClick, icon, title }) => {
  return (
    <li>
      <ButtonSidebar onClick={onClick}>
        <Icon>{icon}</Icon>
        {title}
      </ButtonSidebar>
    </li>
  );
};

const ButtonSidebar = styled.div`
  position: relative;
  
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: left;

  border: none;
  border-top-right-radius: 15px;
  border-bottom-right-radius: 15px;
  font-weight: 350;
  transition: all 0.2s ease-in;
  color: ${colors.onSecContainer};

  height: 70px;

  &:hover {
    background: ${colors.SurfContainer_highest};
  }

  &.active {
    background: ${colors.secContainer};
    color: ${colors.onPrimContainer};
    transition: all 0.4s ease-in-out;
    font-weight: 400;
  }
`;

const Icon = styled.div`
  margin-right: 15px;
  margin-left: 20px;
  height: 24px;
`
export default SideBarButton;

2. SideNavbar.jsx - This is the sidebar built with above mentioned SidebarButton component.

import React from "react";
import styled from "styled-components"; // Import styled-components only once
import SideBarButton from "./SideNavBarLinks";

import { colors } from "../../assets/colorPalette";
import dashboard from "../../assets/dashboard.svg";
import patient from "../../assets/patient.svg";
import messages from "../../assets/messages.svg";
import visits from "../../assets/visits.svg";

const SideNavbar = ({onSideNavBarClick}) => {
    const handleClick = (page) => {
        onSideNavbarClick(page)
    }
    return (
        <SidebarWrapper>
            <SidebarBody>
                <UnorderedList>
                    {makeButtons.map((btn, i) => (
                        <SideBarButton onClick = {() => handleClick(btn.title)}
                            to={btn.to}
                            icon={btn.icon}
                            title={btn.title}
                            key={i}
                        />
                    ))}
                </UnorderedList>
            </SidebarBody>
        </SidebarWrapper>
    );
};

const makeButtons = [
    {
        to: "/DoctorDashboard",
        icon: <img src={dashboard} alt="dashboard" />,
        title: "Dashboard",
    },
    {
        to: "/Patients",
        icon: <img src={patient} alt="patient" />,
        title: "Patients",
    },
    {
        to: "/Appointments",
        icon: <img src={visits} alt="appointments" />,
        title: "Appointments",
    },
    {
        to: "/Visits",
        icon: <img src={messages} alt="messages" />,
        title: "Visits",
    },
];

const SidebarWrapper = styled.div`
  position: fixed;
  top: 0;
  left: 0;
  width: 250px;
  height: 100vh;
  background: ${colors.SurfContainer};
  z-index: 2;
  transition: transform 0.3s ease-in-out;
`;

const SidebarBody = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  height: 100%;
  padding-top: 20px;
`;

const UnorderedList = styled.ul`
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  display:inline-block;
  width: 100%;
`;

export default SideNavbar;

3. Content.jsx - this page loads the content related to the side bar buttons.

import React from 'react';
import DashboardPage from '../../pages/Doctor/DashboardPage';
import PatientsPage from '../../pages/Doctor/PatientsPage';
import VisitsPage from '../../pages/Doctor/VisitsPage';
import AppointmentsPage from '../../pages/Doctor/AppointmentsPage';
import styled from 'styled-components';

const Content = ({ selectedPage }) => {
  const renderPage = () => {
    switch (selectedPage) {
      case 'Dashboard':
        return <DashboardPage />;
      case 'Patients':
        return <PatientsPage />;
      case 'Appointments':
        return <AppointmentsPage />;
      case 'Visits':
        return <VisitsPage />;
      default:
        // Throw an error for invalid pages
        throw new Error(`Invalid page: ${selectedPage}`);
    }
  };

  return (
    <ContentContainer>{renderPage()}</ContentContainer>
  );
}

const ContentContainer = styled.div`
    display: flex;
    padding: 20px;
`
export default Content;

4. DoctorsUI.jsx - this is the final page, which is the sum of Sidebar and Content components. it is displayed correctly. But the Content pages are not loading correctly.

import React, { useState } from "react";
import styled from "styled-components";
import SideNavBar from "../../components/Doctor/SideNavbar";
import Content from "../../components/Doctor/Content";

const DoctorsUI = () => {
  // State to manage the selected page
  const [selectedPage, setSelectedPage] = useState("Dashboard");

  // Function to handle sidebar button click
  const handleSideNavClick = (page) => {
    setSelectedPage(page);
  };

  return (
    <Wrapper>
      <SidebarWrapper>
        {/* Pass the handleSideNavClick function to SideNavBar */}
        <SideNavBar onSideNavBarClick={{handleSideNavClick}} />
      </SidebarWrapper>
      {/* Pass the selectedPage state to Content */}
      <ContentWrapper>
        <Content selectedPage={selectedPage} />
      </ContentWrapper>
    </Wrapper>
  );
};

const Wrapper = styled.div`
  display: flex;
`;

const SidebarWrapper = styled.div`
  // add suitable styles for a side navigation bar wrapper
  position: fixed;
  top: 0;
  left: 0;
  width: 250px;
  height: 100vh;
  transition: transform 0.3s ease-in-out;
`;

const ContentWrapper = styled.div`
  // add suitable styles for a content wrapper
  flex: 1;
  margin-left: 270px;
  padding: 20px;
`;

export default DoctorsUI;

I tried everything I can as a rookie, I watched YT videos, asked GPTs, spent around 3 days and I got nothing yet I'm trying my best.


Solution

  • Issue

    It would appear you are passing an object with a handleSideNavClick property to SideNavBar's onSideNavBarClick prop, e.g. onSideNavBarClick={{ handleSideNavClick }}.

    <SideNavBar onSideNavBarClick={{ handleSideNavClick }} />
    

    I suspect you ought to see an error in the browser console when attempting to invoke the passed onSideNavBarClick prop, e.g. that it's not a function.

    const SideNavbar = ({ onSideNavBarClick }) => {
      const handleClick = (page) => {
        onSideNavbarClick(page); // <-- not a function, `{ handleSideNavClick }`
      };
    
      ...
    };
    

    Solution

    To fix this you can just pass handleSideNavClick as the onSideNavBarClick value.

    <SideNavBar onSideNavBarClick={handleSideNavClick} />
    
    const SideNavbar = ({ onSideNavBarClick }) => {
      const handleClick = (page) => {
        onSideNavbarClick(page); // <-- a function, `handleSideNavClick`
      };
    
      ...
    };
    

    or

    const SideNavbar = ({ onSideNavBarClick }) => {
      return (
        <SidebarWrapper>
          <SidebarBody>
            <UnorderedList>
              {makeButtons.map(({ title, ...btn}, index) => (
                <SideBarButton
                  key={index}
                  onClick={() => onSideNavBarClick(title)} // <-- use directly
                  {...btn}
                />
              ))}
            </UnorderedList>
          </SidebarBody>
        </SidebarWrapper>
      );
    };