How to change content/components within a js react page? - javascript

To clarify I'm working a react page that would show the user one piece of content that will be displayed on the page. When the user clicks on a link to said piece of content that they would like to see on the page.
The structure of the page goes like this. There will be a navbar that is specific to the page. The navbar has links to the components/content I'm also using styled components for this project the navbar looks like this
The servantclassnavbar file.
import react from 'react'
import styled from 'styled-components'
import { Link } from 'react-router-dom'
//useable react icon
import {FaCaretDown} from 'react-icons/fa'
const Navbarcontainer = styled.ul`
background: #D3D3D3;
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
display: flex;
justify-content: center;
`
const Dropdownbtn = styled.div`
display: inline-block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
cursor: pointer;
&:hover{
color: cyan;
background: grey;
transition: ease-in-out 0.5s;
}
`
const Dropdowncontent = styled.div`
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
`
const Dropdownli = styled.li`
display: inline-block;
&:hover {
color: cyan;
background: grey;
transition: ease-in-out 0.4s;
}
&:hover ${Dropdowncontent} {
display: block;
}
`
const Dropdownnavlinks = styled(Link)`
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: left;
&:hover {
color: cyan;
background-color: grey;
transition: ease-in-out 0.4s;
}
`
function Servantclassesnavbar(){
return(
<>
<Navbarcontainer>
<Dropdownli>
<Dropdownbtn>
Knight Classes<FaCaretDown />
</Dropdownbtn>
<Dropdowncontent>
<Dropdownnavlinks to="/saberclass">Saber</Dropdownnavlinks>
<Dropdownnavlinks to="/archerclass">Archer</Dropdownnavlinks>
<Dropdownnavlinks to="/lancerclass">Lancer</Dropdownnavlinks>
</Dropdowncontent>
</Dropdownli>
</Navbarcontainer>
</>
)
}
export default Servantclassesnavbar;
Here is a the page that I want to have it act as a home page for the all the other components to display their content in. You can ignore the 'Navbar' and 'sidebar' they are just navigations to other pages for this site.
import React,{useState} from "react";
import Navbar from "../componets/navbar";
import Sidebar from "../componets/sideBar";
import styled from "styled-components";
import Servantclassesnavbar from "../servantclassescomponets/servantclassesnavbar";
import Introduction from "../servantclassescomponets/Introduction"
import Saberclass from '../servantclassescomponets/Saberclass'
import Lancerclass from '../servantclassescomponets/Lancerclass'
import Archerclass from "../servantclassescomponets/Archerclass"
import {BrowserRouter as Router, Switch, Route} from "react-router-dom";
const Displayedserventclasscontainer = styled.div`
border: 1px solid black;
margin: auto;
width: 95vw;
height: 280vw;
background: rgb(130,141,162);
background: linear-gradient(274deg, rgba(130,141,162,0.938813025210084) 0%, rgba(66,116,150,0.6306897759103641) 50%, rgba(132,152,187,1) 100%);
#media screen and (max-width: 1024px){
min-height: 100vh;
}
#media screen and (max-width: 768px){
min-height: 230vh;
}
#media screen and (max-width: 540px){
min-height: 320vh;
}
#media screen and (max-width: 414px){
min-height: 350vh;
}
#media screen and (max-width: 375px){
min-height: 415vh;
}
#media screen and (max-width: 360px){
min-height: 450vh;
}
#media screen and (max-width: 320px){
min-height: 530vh;
}
`;
function Servantclasses (){
const [isOpen, SetIsOpen] = useState(false);
function toggle (){
SetIsOpen(!isOpen)
}
return(
<>
<Navbar toggle={toggle}/>
<Sidebar isOpen={isOpen} toggle={toggle}/>
<Servantclassesnavbar />
<Displayedserventclasscontainer>
<Router>
<Switch>
<Route path="/" component={Introduction} />
<Route path="/saberclass" component={Saberclass} />
<Route path="/lancerclass" component={Lancerclass} />
<Route path="/archerclass" component={Archerclass} />
</Switch>
</Router>
</Displayedserventclasscontainer>
</>
)
}
export default Servantclasses;
Last here is an example of the component/content I'm trying to display on the page.
import react from 'react'
import styled from 'styled-components'
import sabercard from '../assets/sabercard.png'
const Maincontainer = styled.div`
margin: auto;
width: 75vw;
height: 275vw;
text-align: center;
`
const Classnameheader = styled.h1`
margin-bottom: 2%;
font-size: 2.5rem;
border-bottom: 3px solid black;
`
const Classcardimg = styled.div`
display: flex;
justify-content: center;
border-bottom: 3px solid black;
> img {
width: 15vw;
height: 30vw;
}
`
const Loreheadercontainer = styled.h2`
font-size: 2rem;
border-bottom: 3px solid black;
`
const Classlorecontainer = styled.div`
font-size: larger;
`
<Maincontainer>
<Classnameheader>Saber</Classnameheader>
<Classcardimg><img src={sabercard} alt="The Servant class card image" /></Classcardimg>
<Loreheadercontainer>Saber Lore</Loreheadercontainer>
<Classlorecontainer>Servants that are placed in this class are legendary figures who took up the sword in their life.
some are known for choosing to master their swordsmanship. others only used it briefly, but they are a Saber all the same.</Classlorecontainer>
At first I tried using react-router as you can see in the page file that houses all the content, and that's when I realize that react-router changes the whole page leaving a blank page. How would I make it so when I click on one the links the content with in the page's 'Displayedserventclasscontainer' will display just the content the user wants to see within that page?

Since the Servantclassesnavbar uses the Link component, it should be inside of the Router component as follow:
return(
<Router>
<Navbar toggle={toggle}/>
<Sidebar isOpen={isOpen} toggle={toggle}/>
<Servantclassesnavbar />
<Displayedserventclasscontainer>
<Switch>
<Route path="/" component={Introduction} />
<Route path="/saberclass" component={Saberclass} />
<Route path="/lancerclass" component={Lancerclass} />
<Route path="/archerclass" component={Archerclass} />
</Switch>
</Displayedserventclasscontainer>
</Router>
)
And any component used outside of the Switch will be displayed on all pages, which I think is what you are trying to achieve.

Related

My components keep stacking on themselves when i try to reuse them

I want to use the components i made multiple times while rendering dynamic content
but when i try to render them they just stack up on themselves in the same position
whenever i render the component, multiple times, i dont even see the sliders and the >title stacks up on eachother
import React from "react";
import styled from "styled-components";
import ellipse from "../img/ellipse.png";
import Range from "./Range";
function RangeComp() {
const titlesArr = [
"Cybersecurity",
"Developer",
"DevOps",
"Designer",
"Project Manager",
"Product Manager",
"Marketer",
"Writer",
];
console.log(titlesArr);
return (
<Container>
<Circle />
<Heading>Score your level of interest in these job titles:</Heading>
<Divs>
<Div1>
<Range title={titlesArr[0]} />
<Range title={titlesArr[1]} />
</Div1>
<Div2></Div2>
</Divs>
</Container>
);
}
export default RangeComp;
const Container = styled.div`
position: absolute;
width: 980px;
height: 583px;
left: 650px;
top: 220px;
box-shadow: 0px 4px 29px #f0f3ff;
border-radius: 35px;
:hover {
border: 1px solid black;
}
`;
const Circle = styled.div`
position: absolute;
background-image: url(${ellipse});
width: 30px;
height: 30px;
right: 1.8%;
top: 2%;
background-repeat: no-repeat;
background-size: cover;
`;
const Heading = styled.div`
position: absolute;
width: 400px;
height: 31px;
font-family: "HelveticaNeueCyr";
font-style: normal;
font-weight: 400;
font-size: 20px;
line-height: 155.02%;
color: #30302e;
left: 8%;
top: 10%;
`;
const Divs = styled.div``;
const Div1 = styled.div``;
const Div2 = styled.div``;
Above is where i want to reuse the component but they just stack up on each other
Below is the component i want to reuse
import React, { useState } from "react";
import "./Range.css";
import styled from "styled-components";
import ReactSlider from "react-slider";
function Range(props) {
const [currentValue, setCurrentValue] = useState(0);
return (
<div className="range">
<ReactSlider
className="customSlider"
trackClassName="customSlider-track"
thumbClassName="customSlider-thumb"
marks={1}
min={0}
max={10}
defaultValue={0}
value={currentValue}
onChange={(value) => setCurrentValue(value)}
/>
<h4>{props.title}</h4>
<h1 className="range-value">{currentValue}/10</h1>
</div>
);
}
export default Range;
What's inside your Range.css?
If the position is:
position: absolute;
Then your components will always stack on top of each other because they all have the same style.
You might need to set the position to:
position: relative;
So that the components will position themselves relative to each other.

React js app sidebar selected item not highlighted

I created this react app with a side bar, and it looks pretty good, but one thing I can't figure out is how to mark the item (page link) that was clicked.
Here is the code, I added activeClassName="selected" to the SidebarLink const, and added it to the styled-component, but it's not working.
import React, { useState } from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
const SidebarLink = styled(Link)`
/*border: 3px solid green;*/
display: flex;
color: #e1e9fc;
justify-content: space-between;
align-items: center;
padding: 20px;
list-style: none;
height: 60px;
text-decoration: none;
font-size: 18px;
&:hover {
background: #252831;
border-left: 4px solid #ffbc2e;
cursor: pointer;
}
.selected {
color: red;
}
`;
const SidebarLabel = styled.span`
margin-left: 16px;
`;
/* Used for Training dropdown */
const DropdownLink = styled(Link)`
/*border: 3px solid red;*/
background: #252831;
height: 60px;
padding-left: 3rem;
display: flex;
align-items: center;
text-decoration: none;
color: #f5f5f5;
font-size: 16px;
font-weight: bold;
&:hover {
background: #48526F;
border-left: 4px solid #ffbc2e;
cursor: pointer;
}
`;
const SubMenu = ({ item }) => {
const [subnav, setSubnav] = useState(false);
const showSubnav = () => setSubnav(!subnav);
return (
<>
<SidebarLink to={item.path} onClick={item.subNav && showSubnav} activeClassName="selected" exact>
<div className="sidebarTextContainer">
<div className="sidebarIcon">{item.icon}</div>
<div className="sidebarText"><SidebarLabel>{item.title}</SidebarLabel></div>
</div>
<div>
{item.subNav && subnav
? item.iconOpened
: item.subNav
? item.iconClosed
: null}
</div>
</SidebarLink>
{subnav &&
item.subNav.map((item, index) => {
return (
<DropdownLink to={item.path} key={index}>
{item.icon}
<SidebarLabel>{item.title}</SidebarLabel>
</DropdownLink>
);
})}
</>
);
};
export default SubMenu;
Anyone got any idea please on how to fix this?
Even though you're asking about remembering which item was clicked, I think what you actually want is that the link corresponding to the current page be highlighted as active.
If you're using react-router v6, you should use NavLink instead of Link (docs).
A <NavLink> is a special kind of <Link> that knows whether or not it is "active".
By default, an active class is added to a <NavLink> component when it is active.
You should update the imported component and remove the activeClassName.
const SidebarLink = styled(NavLink)`
// ...
&.active {
color: red;
}
`
// ...
<SidebarLink to={item.path} onClick={item.subNav && showSubnav} exact>
...
</SidebarLink>
If you're using react-router v5, then you should also use NavLink but you have to pass the activeClassName, like you do in your example. In this case you simply need to substitute Link for NavLink.
Also note that you nested CSS syntax is incorrect. It is applied to the children of SidebarLink, not on SidebarLink itself. You'd want to replace .selected { color: red; } with &.selected { color: red }.

React component overlap each other

component Publisher.js and other child components projectStatus.js are overlapping each other when Render the Child component. I don't know what's going wrong and how to fix this. You can see the image
this is my Publisher.js
//import useState hook to create menu collapse state
import React, { useState } from "react";
import {NavLink, Outlet} from "react-router-dom"
//import react pro sidebar components
import {
ProSidebar,
Menu,
MenuItem,
SidebarHeader,
SidebarFooter,
SidebarContent,
} from "react-pro-sidebar";
//import icons from react icons
import { FaFileContract } from "react-icons/fa";
import { FiLogOut} from "react-icons/fi";
import { HiDocumentReport } from "react-icons/hi";
import { BiCog } from "react-icons/bi";
import { GiHamburgerMenu } from "react-icons/gi";
//import sidebar css from react-pro-sidebar module and our custom css
import "react-pro-sidebar/dist/css/styles.css";
import "./publisherCss.css";
const Publisher = () => {
//create initial menuCollapse state using useState hook
const [menuCollapse, setMenuCollapse] = useState(false)
//create a custom function that will change menucollapse state from false to true and true to false
const menuIconClick = () => {
//condition checking to change state from true to false and vice versa
menuCollapse ? setMenuCollapse(false) : setMenuCollapse(true);
};
return (
<>
<div id="sidebarHeader">
{/* collapsed props to change menu size using menucollapse state */}
<ProSidebar collapsed={menuCollapse}>
<SidebarHeader>
<div className="logotext">
{/* small and big change using menucollapse state */}
<p>{menuCollapse ? "Evc" : "Publisher "}</p>
</div>
<div className="closemenu" onClick={menuIconClick}>
{/* changing menu collapse icon on click */}
{menuCollapse ? (
<GiHamburgerMenu/>
) : (
<GiHamburgerMenu/>
)}
</div>
</SidebarHeader>
<SidebarContent>
<Menu iconShape="square">
<NavLink to="/publisher/projectstatus"> <MenuItem icon={<FaFileContract />}>Project status</MenuItem> </NavLink>
<MenuItem icon={<HiDocumentReport />}>All project</MenuItem>
<MenuItem icon={<BiCog />}>Settings</MenuItem>
</Menu>
</SidebarContent>
<SidebarFooter>
<NavLink to="/login">
<Menu iconShape="square">
<MenuItem icon={<FiLogOut />}>Logout</MenuItem>
</Menu>
</NavLink>
</SidebarFooter>
</ProSidebar>
</div>
<Outlet />
</>
)
}
export default Publisher;
Publisher.css
#sidebarHeader {
position: absolute;
width: 220px;
display: flex;
}
#sidebarHeader .pro-sidebar {
height: 100vh;
/* position: absolute; */
}
#sidebarHeader .closemenu {
color: rgb(0,7,61);
position: absolute;
right: 0;
z-index: 9999;
line-height: 20px;
border-radius: 50%;
font-weight: bold;
font-size: 22px;
top: 55px;
cursor: pointer;
}
#sidebarHeader .pro-sidebar {
width: 100%;
min-width: 100%;
}
#sidebarHeader .pro-sidebar.collapsed {
width: 80px;
min-width: 80px;
}
#sidebarHeader .pro-sidebar-inner {
background-color: white;
box-shadow: 0.5px 0.866px 2px 0px rgba(0, 0, 0, 0.15);
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout {
overflow-y: hidden;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout .logotext p {
font-size: 20px;
padding: 10px 20px;
color: #000;
font-weight: bold;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout ul {
padding: 0 5px;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout ul .pro-inner-item {
color: #000;
margin: 10px 0px;
font-weight: bold;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout ul .pro-inner-item .pro-icon-wrapper {
background-color: #fbf4cd;
color: #000;
border-radius: 3px;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout ul .pro-inner-item .pro-icon-wrapper .pro-item-content {
color: #000;
}
#sidebarHeader .pro-sidebar-inner .pro-sidebar-layout .active {
background-image: linear-gradient(0deg, #fece00 0%, #ffe172 100%);
}
#sidebarHeader .logo {
padding: 20px;
}
#media only screen and (max-width: 720px) {
html {
overflow: hidden;
}
}
.nav-link .active{
background-color: #ffe172;
}
I think I am doing some wrong CSS override property but I am unable to understand what's wrong I am doing. if anyone know please correct me
if anyone knows how to fix this please tell me. it's appreciated
update:
After updating the CSS display: flex it show the child content in flex but the problem is, I specified width: 220px for the sidebar but the child content not go above the 220px width. you can see the image.
Now how can I fix this to a child can use width?
Your picture is not complete, most likely it's styles or wrong location of "Outlet". I made simplified example, I hope it helps.

React Redux Image Wont load

So this could honestly be as simple as just over looking it and staring for so long and being new to react but on my section component I'm loading in my backgroundImg prop wont load the image and I cant figure it out. My pictures are in the public folder and my code is in the src components folder
Also, I can get images to load in the file just not when I'm calling them through prop
Home.js This is where I am calling my component and trying to load the file in through the prop type
import React from 'react'
import styled from 'styled-components'
import Section from './Section'
function Home() {
return (
<Container>
<Section
title="Model S"
description="Order Online for Touchless Delivery"
backgroundImg='/public/pictures/model-s.jpg'
leftBtnText="Custom Order"
rightBtnText="Existing Inventory"
/>
<Section
title="Model E"
description="Order Online for Touchless Delivery"
backgroundImg=".\Pictures\model-e.jpg"
leftBtnText="Custom Order"
rightBtnText="Existing Inventory"
/>
<Section />
<Section />
</Container>
)
}
export default Home
//Home and styled help you stlye the component without using css
const Container = styled.div`
height: 100vh;
`
Section.js The component for the Screen
import React from 'react'
import styled from 'styled-components'
//props are just parameters you can set when calling the component
function Section(props) {
return (
<Wrap bgImg={props.backgroundImg}>
<ItemText>
<h1>{props.title}</h1>
<p>{props.description}</p>
</ItemText>
<Buttons>
<ButtonGroup>
<LeftButton>
{props.leftBtnText}
</LeftButton>
<RightButton>
{props.rightBtnText}
</RightButton>
</ButtonGroup>
<DownArrow src='/Pictures/down-arrow.svg' />
</Buttons>
</Wrap>
)
}
export default Section
const Wrap = styled.div`
width: 100vw;
height: 100vh;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
`
const ItemText = styled.div`
padding-top: 15vh;
text-align: center;
`
const ButtonGroup = styled.div`
display: flex;
margin-bottom: 30px;
#media (max-width: 786px){
flex-direction: column;
}
`
const LeftButton = styled.div`
background-color: rgba(23, 26, 32, 0.8);
height: 40px;
width: 256px;
color: white;
display: flex;
justify-content: center;
align-items: center;
border-radius: 100px;
opacity: 0.85;
text-transform: uppercase;
font-size: 12px;
cursor: pointer;
margin: 8px;
`
const RightButton = styled(LeftButton)`
background: white;
opacity: 0.65;
color: black;
`
const DownArrow = styled.img`
margin-top: 20px;
height: 40px;
overflow-x: hidden;
animation: animateDown infinite 1.5s;
`
const Buttons = styled.div`
`
Thanks for the help.
I haven't tested this, but it looks like you didn't use the Wrap bgImg prop in the styled component. There is background-size, background-position, background-repeat, but not background-image using the prop.
Example:
background-image: ${props => props.bgImg || ''};
https://styled-components.com/docs/basics#passed-props

Styling a Router Link with styled-components

What is the best way to style the Link using the styled-components library in the code that follows.
I can find lots of examples to work with anchor tag but none to work with react-router link.
Am I going about the correct way.
import React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
const Nav = ({ className }) => {
return (
<div className={className}>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</div>
);
};
export default styled(Nav)`
color: white;
text-align: left;
background: teal;
width: 100%;
ul {
color: red;
display: flex;
flex-direction: row;
border: 1px solid green;
list-style: none;
li {
padding: 15px 15px;
border: 2px solid purple;
}
}
`;
Thanks
Joseph Shanahan
Yes thanks for your help. A slimmed down version of what I will implement is as follows.
It also has the advantage in that I did not have to implement an unordered list.
import React from "react";
import { Link } from "react-router-dom";
import styled from "styled-components";
const Nav = ({ className }) => {
return (
<div className={className}>
<NavLink to="/">Home</NavLink>
<NavLink to="/about">About</NavLink>
</div>
);
};
const NavLink = styled(Link)`
padding: 20px;
color: white;
text-decoration: none;
&:hover {
color: red;
background: blue;
}
`;
export default styled(Nav)`
color: white;
width: 100%;
display: flex;
justify-content: flex-end;
`;
Thanks Joseph Shanahan
You are in the right way, but little wrong, instead of using ul you just pass the component reference.
export default styled(Nav)`
color: white;
text-align: left;
background: teal;
width: 100%;
${Link} {
/* style for Link Component */
}
`;
Check this answer, it's very familiar.
react-router link translates to after all in <a> tags so style them in the same way you would style an <a> tag
so let's say, you need to change their color to red then:
ul {
color: red;
}
won't work, you will need to do:
ul a {
color: red;
}
If you just want to style the Link component, then the usual way in my experience is to create a styled component like so:
const NavLink = styled(Link)`
/* Link styles */
`
And then just render it like <NavLink>Home</NavLink>.
This also makes it easy to reuse this styled component.

Categories