How to find out which Router component is being rendered in React? - css

I have a Navbar component and I am trying to render it with different CSS styles using styled-components with respect to the component route which is being rendered. How can I check if that component is being rendered or not ?
const NavbarContainer = styled.div`
height: 115px;
font-family: 'Domine', serif;
align-content: center;
align-items: center;
position: absolute;
z-index: 4;
width: 100vw;
overflow: hidden;
&:hover {
background-color: white;
color: black !important;
}
`;
lets say this the component and I want to change position: absolute to position: static in Login page but I want that to stay that as position: absolute in the home page. How can I achieve this?

Create a version of the NavbarContainer specific for the login route and override the position rule, and use layout routes to render the appropriate routes with the appropriate layout/navbar.
Example:
const NavbarContainer = styled.div`
height: 115px;
font-family: 'Domine', serif;
align-content: center;
align-items: center;
position: absolute;
z-index: 4;
width: 100vw;
overflow: hidden;
&:hover {
background-color: white;
color: black !important;
}
`;
const StaticNavbarContainer = styled(NavbarContainer)`
position: static;
`;
...
import { Outlet } from 'react-router-dom';
const NavbarLayout = ({ children }) => (
<>
<NavbarContainer>{children}</NavbarContainer>
<Outlet />
</>
);
const StaticNavbarLayout = ({ children }) => (
<>
<StaticNavbarContainer>{children}</StaticNavbarContainer>
<Outlet />
</>
);
...
<Routes>
<Route
element={(
<NavbarLayout>
// ... render links here as children
</NavbarLayout>
)}
>
<Route path="/" element={<Home />} />
// ... routes to render with absolute positioned navbar
</Route>
<Route
element={(
<StaticNavbarLayout>
// ... render links here as children
</StaticNavbarLayout>
)}
>
<Route path="/login" element={<Login />} />
// ... other routes with static positioned navbar
</Route>
// ... other routes without navbars
</Routes>

One idea would be to wrap your component inside another
like
In Login page
const NavWrapper = styled.div`
>div{
position: static
}
`
<NavWrapper>
<NavbarContainer/>
</NavWrapper>

You can achieve this with conditional styled based on login path
<Appbar style={{ position: pathname === '/login' ? 'static' : 'absolute' }}></Appbar>

Related

How do I reference another component's styled-components generated className while creating a (hover) rule in a different component?

I'm creating a menu with styled-components and React, and want the color of the icon to change on hover, but I need it to change when the icon's parent is hovered, so that hovering the text next to the icon also activates the icon's hover styles. Here is the code I'm using to get close:
import React from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
const Menu = styled.div`
display: flex;
flex-direction: column;
`;
const LinkContainer = styled.div`
display: flex;
flex-direction: row;
`;
const FontAwesomeIconExtended = styled.div`
flex: 1;
display: grid;
place-items: center;
height: 40px;
width: 40px;
padding: 10px 2px;
border-radius: 10px;
transition: color 0.5s ease;
color: ${(props) => (props.$isactive ? '#fff' : '#CBE3EB')};
background: ${(props) =>
props.$isactive
? 'linear-gradient(96.34deg, #004157 0%, #0090b2 100%)'
: '#fff'};
${LinkContainer}:hover & {
color: ${(props) => (props.$isactive ? '#fff' : 'green')};
} /* Problem occurring here */
`;
const LinkText = styled.div`
flex: 1 0 100px;
`;
function NavLink({ ...props }) {
return (
<Link to={props.path}>
<LinkContainer $isactive={props.$isactive}>
<FontAwesomeIconExtended
$isactive={props.$isactive}
icon={props.icon}
size='2x'
as={FontAwesomeIcon}
/>
<LinkText $isactive={props.$isactive}>{props.name}</LinkText>
</LinkContainer>
</Link>
);
}
export default function NavMenu() {
return (
<Menu>
<NavLink path='/' name='Home' icon='house' $isactive />
<NavLink path='/profile' name='Profile' icon='user' />
<NavLink path='/payments' name='Payments' icon='credit-card-front' />
<NavLink path='/contracts' name='Contracts' icon='file-contract' />
<NavLink path='/messages' name='Messages' icon='mail-bulk' />
<NavLink path='/messages' name='Documents' icon='folders' />
<NavLink path='/locations' name='Transfer' icon='truck-moving' />
</Menu>
);
}
The way you reference another styled component in a later component is very clever, but in this case when it creates the hover rule, it creates without consideration of the different type of parent container ($isactive === true, or $isactive === false), so all LinkContainers have two rules for hovering, and use the last defined rule. This can be seen by moving $isactive to the last NavLink component.
Here is a screenshot of the devtools showing what I mean about the two hover rules not taking into consideration the parents class, just the general type of the parent.
I think the solution might involve being specific about the two types of LinkContainer's classNames while creating the hover rule, but that doesn't seem well supported. Thanks for taking a look.
Increase the specificity by repeating the class name, using another '&'
${LinkContainer}:hover && {

How to remove styling from Link of react router with styled-components

I'm using styled-components but in a different file. I've searched for this question and found many answers, but I'm still confused about how to apply it in my code version. So, sorry in advance if it will be repetitive.
File Main.jsx :
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
function Main() {
return (
<>
<Router>
<MainComponent>
<Menu>
<Link to="/crypto">
<HyperLink>Crypto</HyperLink>
</Link>
<Link to="/marketplace">
<HyperLink>Market Place</HyperLink>
</Link>
</Menu>
<Switch>
<Route path="/crypto" component={Crypto} />
<Route path="/marketplace" component={MarketPlace} />
</Switch>
</MainComponent>
</Router>
</>
);
}
File MainElements.jsx:
import styled from "styled-components";
export const MainComponent = styled.div`
width: 100%;
height: 100vh;
background-color: #1e2258;
`;
export const Menu = styled.div`
display: flex;
width: 80%;
margin: auto;
height: 10vh;
color: #fff;
border: 1px solid white;
align-items: center;
`;
export const HyperLink = styled.p`
text-decoration: none;
&:focus,
&:hover,
&:visited,
&:link,
&:active {
text-decoration: none;
}
`;
Can try example from react-router docs https://reactrouter.com/web/api/Link/component-reactcomponent
Just use a tag instead of p for link.
const FancyLink = React.forwardRef((props, ref) => (
<HyperLink ref={ref} {...props}>{props.children}</HyperLink>
))
<Link to="/" component={FancyLink} />
const CustomLink = ({ ...props }) => <Link component={FancyLink} {...props} />

Change navbar background color on other routes in ReactJS

I have following react code.
the code
What I would like is to just when I click on "about" menu background color should change from red to blue otherwise stay in red.
in another scenario:
(my problem is how to access to links "route" or "path" in react because i want to add condition like ==> if (path =="./about) do somthing...)
is there any way to do this? i would appreciate for your help.
If you are using react-router-dom
Then you can use the useLocation hook to get the current location
First import it
import { useLocation } from 'react-router-dom';
Then get the location
const location = useLocation();
You can use a useEffect hook to change the background color whenever the location changes
useEffect(()=>
{
if(location.pathname == '/about'){
// Change background color
}
}
},[location])
This should work for you
Try to include this code in your App.js
Following code works:
const Nav = styled.nav`
height: 100px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
padding: 0px 10px;
width: 100%;
z-index: 100;
/* background-color: red; */
`;
const Menu = styled.div`
display: flex;
flex-wrap: wrap;
gap: 20px;
align-items: center;
justify-content: center;
`;
const Navbar = ({ toggle }) => {
const [navBg, setNavBg] = React.useState("red");
const location = useLocation();
React.useEffect(() => {
if (window.location.pathname === "/about") {
setNavBg("yellow");
} else {
setNavBg('red')
}
}, [location]);
return (
<Nav style={{ backgroundColor: navBg }}>
<h1 to="/">logo</h1>
<Menu>
<Link to="/">home</Link>
<Link to="/about">about</Link>
<Link to="/services">services</Link>
</Menu>
</Nav>

props is not applied although passed it to styled component

What I want to do
Changing colors depending on props passed from a component using styled component.
Problem
SmallButton component definitely gets props but it doesn't change like props indicates.
I would like to change styles of SmallButton depending on props that a component gives to the button component.
SmallButton has these props but it doesn't change at all.
I would like you to teach me how to solve it.
Thank you very much.
=== ==== === ===
My code is like this.
Header.jsx
render() {
return (
<>
<Wrapper>
{/* CSS Grid( 1 : 1 : 1) 左 */}
<Image src={Logo} alt="" />
{/* CSS Grid( 1 : 1 : 1) 中央 */}
<SearchBox />
{/* CSS Grid( 1 : 1 : 1) 右 */}
{this.props.isAuthenticated ? (
<>
<div>
<MessageToUserDiv>
<span>Hello {this.state.loginUser.username}</span> 
<LogoutButton onClick={this.handleLogout}>Logout</LogoutButton>
</MessageToUserDiv>
<AuthButtonDiv>
<SmallButton
btn_border="#466A80"
btn_back="#466A80"
btn_text_color="#D9F1FF"
btn_name="Post"
btn_click={this.jumpToPostGive}
/>
<SmallButton
btn_border="#466A80"
btn_back="#8DD6FF"
btn_text_color="#466A80"
btn_name="Info"
btn_click=""
/>
</AuthButtonDiv>
</div>
</>
) : (
<>
<div>
<p>Hello Guest</p>
<AuthButtonDiv>
<SmallButton btn_name="Register" btn_click={this.jumpToRegister} />
<SmallButton btn_name="Login" btn_click={this.jumpToLogin} />
</AuthButtonDiv>
</div>
</>
)}
</Wrapper>
</>
);
}
}
const Wrapper = styled.div`
background-color: #8dd6ff;
width: 100%;
display: grid;
grid-template-columns: 1fr 2.3fr 1fr;
padding: 10px 5px 5px 5px;
`;
const Image = styled.img`
width: 230px;
margin-top: 5px;
`;
const MessageToUserDiv = styled.div`
font-size: 13px;
text-align: right;
height: 20%;
`;
const LogoutButton = styled.button`
color: #6e787f;
width: 30%;
`;
const AuthButtonDiv = styled.div`
display: flex;
justify-content: space-around;
align-items: flex-end;
height: 80%;
`;
SmallButton.jsx
class SmallButton extends Component {
constructor(props) {
super(props);
}
render() {
return (
<StyledButton
type={this.props.btn_type}
onClick={this.props.btn_click}
onSubmit={this.props.btn_submit}
disabled={this.props.btn_disable}
>
{this.props.btn_name}
</StyledButton>
);
}
}
const Colors = {
main: '#8DD6FF',
characters: '#6C7880',
subcolor1: '#D9F1FF',
accent1: '#70AACC',
accent2: '#466A80',
};
const StyledButton = styled.button`
font-size: 1.18em;
border-radius: 7px;
height: 45px;
width: 100px;
padding: 2px 3.5px;
border: solid 2.5px;
border-color: ${(props) => props.btn_border};
background: ${(props) => props.btn_back};
color: ${(props) => props.btn_text_color};
`;
spread the rest for your props to StyledButton like this:
<StyledButton
type={this.props.btn_type}
onClick={this.props.btn_click}
onSubmit={this.props.btn_submit}
disabled={this.props.btn_disable}
{...this.props}
>
{this.props.btn_name}
</StyledButton>

Conditionally Render CSS Based On Route (React)

Here is my App.js component so far:
function App() {
return (
<div className="App">
<Router>
<NavBar />
<Switch>
<Route exact path='/' component={HomepageLayout} />
<Route exact path='/post/:id' component={Post}/>
</Switch>
</Router>
</div>
);
}
I need to render the CSS value of a class based on the route that is being rendered. When the HomepageLayout component is rendered, I need the following:
styles.css
.ui.inverted.vertical.center.aligned.segment{
position: fixed;
left: 0px;
top: 0px;
width: 100%;
z-index: 2;
}
Then, I need to change the values for this target when the Post component is rendered so that the styles are basically removed:
styles.css
.ui.inverted.vertical.center.aligned.segment{
position: none;
left: none;
top: none;
width: none;
z-index: none;
}
Is there a way to change the styles for a particular CSS class tag based on the route? I have seen examples using , but is there a way to do this with / ?
use it like this
<Component header />
// component
const Component = ({header}) => {
const conditionalClass = header ? 'yesHeader' : 'noHeader';
return (
<p className={conditionalClass}>this is </p>
)
}
you can use this as well

Resources