The "isActive" prop for React's NavLink isn't working - css

I'm making a little ticker animation for my navbar but for some reason, the ticker doesn't move when I click on a NavLink. At first, I thought it was a problem with the CSS file but that seems to be working fine. I then tried using an older version of react-router-dom but that also didn't seem to work. Some help would be appreciated.
As you can see, the 'active-nav' class is supposed to change to any NavLink that is Active & the rest are left with empty quotation marks.
Navbar.jsx:
import {Link, NavLink} from 'react-router-dom'
import {links} from '../data'
import {GoThreeBars} from 'react-icons/go'
import Logo from '../images/logo.png'
import "./navbar.css"
const Navbar = () => {
return (
<nav>
<div className='container nav__container'>
<Link to="/" className='logo'>
<img src={Logo} alt="Nav Logo"/>
</Link>
<ul className="nav__links">
{
links.map(({name, path}, index) => {
return (
<li>
<NavLink to={path} className={({isActive}) => isActive ? 'active-nav' : ''}>{name}</NavLink>
</li>
)
})
}
</ul>
<button className="nav__toggle-btn">
<GoThreeBars />
</button>
</div>
</nav>
)
}
export default Navbar
Here you can see that most of the functionality is in the CSS
navbar.css:
nav {
height: 5rem;
width: 100vw;
background: var(--color-primary);
display: grid;
place-items: center;
position: fixed;
top: 0;
left: 0;
z-index: 99;
}
/* only shows on medium and small screens */
.nav__toggle-btn {
display: none;
}
.nav__container {
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
width: 1920px;
}
.logo {
width: 7rem;
margin-right: 400px;
}
.nav__links {
display: flex;
gap: 3.5rem;
}
.nav__links a {
transition: var(--transition);
}
.nav__links a:hover {
color: var(--color--secondary);
}
.active-nav {
position: relative;
}
.nav__links::after {
content: '';
display: block;
width: 1.2rem;
height: 1.2rem;
background: var(--color-primary);
position: absolute;
left: calc(50% - 0.6rem);
transform: rotate(45deg);
margin-top: 2.7rem;
}
package.json
{
"name": "reactappblue",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^13.4.0",
"#testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.6.0",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
app.js:
import {BrowserRouter, Routes, Route} from 'react-router-dom'
import Home from './pages/home/Home'
import About from './pages/about/About'
import Contact from './pages/contact/Contact'
import Gallery from './pages/gallery/Gallery'
import Plans from './pages/plans/Plans'
import Trainers from './pages/trainers/Trainers'
import NotFound from './pages/notfound/Notfound'
import Navbar from './components/Navbar'
import {BrowserRouter as Router} from 'react-router-dom'
const App = () => {
return (
<BrowserRouter>
<Navbar />
<Routes>
<Route index element={<Home/>} />
<Route path="about" element={<About/>} />
<Route path="contact" element={<Contact/>} />
<Route path="gallery" element={<Gallery/>} />
<Route path="plans" element={<Plans/>} />
<Route path="trainers" element={<Trainers/>} />
<Route path="*" element={<NotFound/>} />
</Routes>
</BrowserRouter>
)
}
export default App

It's rather hard to exactly reproduce your problem since you are missing some relevant information in your question. I made some assumptions:
Your package.json would have been valuable since it contains the versions of the packages you're using, I used "react": "18.2.0" and "react-router-dom": "6.4.2"
I wrapped the Navbar in a react-router-dom BrowserRouter in the parent component like this:
import Navbar from './Navbar.jsx';
import {BrowserRouter as Router} from 'react-router-dom'
function App() {
return (
<Router>
<div className="App">
<Navbar/>
</div>
</Router>
);
}
Doing so, the class name was set properly for me. I didn't have to change any parts of the code you provided.
I hope this already helps, if not, please provide the versions of the packages you're using and how the <Navbar /> component is instantiated in its parent component(s).

You can simply use activeClassName prop.
<NavLink to={path} activeClassName="active-nav">{name}</NavLink>
If you are using className you don't need to destructure {isActive}, simply use
<NavLink
to={path}
className={isActive => isActive ? 'active-nav' : ''}
>
{name}
<NavLink/>

Related

React.js + CSS: Splash Screen Animation to FadeOut

"leaflet": "^1.9.2",
"react": "^18.2.0",
I've built a web app using React frontend and Leaflet. The amount of data (over 3,000 objects) means the app has a 3-6 second lag when loading the page. To combat this my idea was to build a "splash screen".
.css
animation: fadeOut 1s linear forwards;
animation-delay: 5s;
width: 101%;
height: 101vh;
background-color: #428bca;
color: whitesmoke;
z-index: 99999999;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
#keyframes fadeOut {
0% {
opacity: 1;
visibility:visible;
}
100% {
opacity: 0;
visibility:hidden;
}
}
App.js
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Splash from "./components/Splash";
import Footer from "./components/Footer";
import Navbar from "./components/Nav";
import MapPage from "./pages/MapPage";
import Admin from "./pages/Admin";
import "./index.css";
import "./App.css";
import "./styles/splash.css";
import logoimg from "./img/logo.png";
function App() {
// function will move to a component once it's complete and working.
function splash() {
return (
<main id="splash-bck">
<article id="splash-container">
<img
src={logoimg}
style={{
width: "35%",
}}
/>
<p id="splash-tagline">
<em>Input your location to find warm spaces near you</em>
</p>
<div id="splash-search">
<input
type="text"
placeholder="ex: Sheffield"
style={{
border: "3px solid #428bca",
borderWidth: "2px",
borderStyle: "solid",
borderColor: "#428bca",
borderRadius: "1.5rem",
color: "grey",
padding: ".5rem",
fontSize: "1.3rem",
textAlign: "center",
}}
/>
</div>
</article>
</main>
);
}
return (
<>
<Router>
{splash()}
{/* <Splash /> */}
<div className="overlay">
<Navbar />
</div>
<Routes>
<Route index element={<MapPage />} />
<Route path="/admin" element={<Admin />} />
</Routes>
<Footer />
</Router>
</>
);
}
export default App;
I've tried different transition types and 'display: none; / visibility: hidden' where both give the same results. The idea is to show a component for 6s before it transitions (fade-out) to show the map underneath. What i currently get is the transition fades out to a white/blank page.

CSS How to fix 'Invalid property value'

I'm creating a React component library using the TSDX react-with-storybook template. However, I can't seem to get CSS to work in my components via import.
Here is a my button component:
import React, { FC, HTMLAttributes } from 'react';
import './button.css';
export interface ButtonProps extends HTMLAttributes<HTMLButtonElement> {
text: string;
}
export const Button: FC<ButtonProps> = ({ text }) => {
return <button className="button">{text.toLowerCase()}</button>;
};
Here is my css:
.button {
background: '#97C339';
border-radius: '30px';
color: 'white';
border: 'none';
cursor: 'pointer';
font-size: '18px';
height: '60px';
width: '180px';
}
When viewing my button story in the browser the button has no styling and shows 'invalid property value':
What are the best practises in terms of applying css to a react based library?
Here is my package.json:
"devDependencies": {
"#babel/core": "^7.15.8",
"#size-limit/preset-small-lib": "^6.0.2",
"#storybook/addon-essentials": "^6.3.10",
"#storybook/addon-info": "^5.3.21",
"#storybook/addon-links": "^6.3.10",
"#storybook/addons": "^6.3.10",
"#storybook/react": "^6.3.10",
"#types/react": "^17.0.28",
"#types/react-dom": "^17.0.9",
"babel-loader": "^8.2.2",
"husky": "^7.0.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-is": "^17.0.2",
"rollup-plugin-postcss": "^4.0.1",
"size-limit": "^6.0.1",
"tsdx": "^0.14.1",
"tslib": "^2.3.1",
"typescript": "^4.4.3"
}
Not a problem with your React environment, its just that your css is invalid.
Theres no need to encapsulate your css property values in ticks (there are some occasions you need ticks, but none of your's need em).
.button {
background: #97C339;
border-radius: 30px;
color: white;
border: none;
cursor: pointer;
font-size: 18px;
height: 60px;
width: 180px;
}
Removing the ticks should do the trick.

Doing custom hover animation on nav items(bootstrap nav) but the effect isn't visible in my react application

I'm trying to add custom hover effect on my nav Items using ext CSS but when I import it in my Navbar the bootstrap isn't overwritten and the effect isn't visible and also when the navBar collapses the three line isn't visible but when I click on the top right corner it's there and works fine
**
Here is my NAVBAR.JS file for react
**
import React, { Component } from 'react';
import { Navbar, Nav, Button } from 'react-bootstrap';
import styles from './Navbar.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Link } from 'react-router-dom';
const links = [
{
href: '/novels/601e73a75e4fd540506c9938',
text: 'Novel',
},
{ href: '#', text: 'Buy EA Coins' },
{ href: '#', text: 'Get Started' },
{ href: '#', text: 'Library' },
{ href: '/', text: 'home' },
];
const createNavItem = ({ href, text, className }) => (
<Nav.Item>
<Nav.Link className={className}>
<Link to={href}> {text}</Link>
</Nav.Link>
</Nav.Item>
);
class NavbarMain extends Component {
constructor(props) {
super(props);
this.state = {
key: 'home',
};
this.handleSelect = this.handleSelect.bind(this);
}
handleSelect(key) {
this.setState({
key: key,
});
alert(`selected ${key}`);
}
render() {
return (
<Navbar
bg="light"
variant="danger"
expand="lg"
fixed-top
className={styles.test}
>
<Navbar bg="light">
<Navbar.Brand>
<Link to="/" exact>
<img
src="EA-Logo-edit.png"
width="90"
height="70"
margin="none"
className="d-inline-block align-top"
alt="React Bootstrap logo"
style={{ margin: 'none' }}
/>
</Link>
</Navbar.Brand>
</Navbar>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto" activeKey="/" className={styles.avbar}>
{links.map(createNavItem)}
</Nav>
<Nav className="ml-auto" navbar>
<Nav.Item>
<Nav.Link href="#discord">
<Button variant="outline-dark">
<img height={25} width={40} src="discord.svg" alt="" />
Discord
</Button>
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link href="/auth/login">
<Button variant="outline-dark">
<img height={25} width={40} src="google.svg" alt="" />
Login
</Button>
</Nav.Link>
</Nav.Item>
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
}
export default NavbarMain;
Here is my CSS file
:local(.navbar.hover::before){
position: relative;
}
:local(.navbar:before){
content: "";
position: absolute;
width: 100%;
height: 2px;
bottom: 0;
left: 0;
background-color: #000;
visibility: hidden;
transform: scaleX(0);
transition: all 0.3s ease-in-out 0s;
}
:local(.navbar:hover){
color: #000;
}
:local(.navbar){
position: relative;
color: #000;
text-decoration: none;
}
You can fix overwrite problem with !important like this
:local(.navbar:hover){
color: #000 !important;
}

When reusing component, my CSS doesn't get applied to it

I am trying to figure out how something like this might occur. Bear with me, since the details might be a little bit sloppy.
I have a Header Component which simply takes up all the viewport, and then adds a NavigationBar Component. The Header Component works just fine in the other place I used it, but for some reason, when I tried reusing it just now, the NavigationBar inside it gets funky (all CSS is simply gone).
Here is the Header component that has the following styling (which works btw): {position: relative;
height: 100vh;
width: 100%;}
import React from "react";
import NavigationBar from "../NavigationBar/NavigationBar";
import "./Header.css";
const Header = (props) => (
<div className="blog-header">
<NavigationBar />
{props.children}
</div>
);
export default Header;
My NavigationBar is a simple React-Bootstrap Navbar (I have decided to delete what was inside navigationItems because I don't think those matter to the problem at hand):
import React from "react";
import { Container, Navbar, Nav, NavbarBrand } from "react-bootstrap";
import Logo from "../Logo/Logo";
import "./NavigationBar.css";
const navigationItems = []
const NavigationBar = (props) => (
<Container>
<Navbar id="navigation" bg="transparent" variant="dark" expand="lg">
<div className="div-brand d-flex flex-grow-1">
<NavbarBrand href="/">
<Logo />
</NavbarBrand>
<div className="w-100 text-right">
<Navbar.Toggle data-toggle="collapse" data-target="#da-navbarNav">
<span className="navbar-toggler-icon"></span>
</Navbar.Toggle>
</div>
</div>
<Navbar.Collapse
className="text-uppercase flex-grow-1 text-right"
id="da-navbarNav"
>
<Nav className="ml-auto flex-nowrap">
{navigationItems.map((navItem, index) => {
return (
<Nav.Item key={index}>
<Nav.Link
id={navItem.id ? navItem.id : null}
href={navItem.path}
className={navItem.classes.join(" ")}
onClick={(event) =>
props.navItemClick(event, window.location.pathname, navItem)
}
>
{navItem.placeholder}
</Nav.Link>
</Nav.Item>
);
})}
</Nav>
</Navbar.Collapse>
</Navbar>
</Container>
);
Navbar.css code:
#navigation {
z-index: 10;
}
#navigation .div-brand {
align-items: center;
}
.navbar-dark .navbar-nav .nav-link {
color: rgba(255, 255, 255, 0.75);
letter-spacing: 1px;
font-size: 0.95rem;
font-weight: bold;
line-height: 24px;
width: 6.4rem;
text-align: center;
}
.navbar-dark .navbar-nav .nav-link:hover,
.navbar-dark .navbar-nav .nav-link:active {
color: #da3833;
}
.navbar-dark #btn-contact {
background-color: #da3833;
border-radius: 3px;
text-align: center !important;
}
.navbar-dark #btn-contact:hover,
.navbar-dark #btn-contact:active {
color: white !important;
}
#media (max-width: 992px) {
.navbar-dark .navbar-nav .nav-link {
text-align: right;
margin-top: 0.2rem;
margin-left: auto;
}
.navbar-dark .navbar-nav .nav-item {
text-align: right;
width: 100%;
}
.navbar-toggler {
outline: none !important;
}
}
I'm currently reusing it inside this component that has as styling the following:
.article-header {
height: inherit;
width: inherit;
position: absolute;
top: 0;
}
import React, { useState, useEffect, useCallback } from "react";
import Header from "../../../components/Header/Header";
import "./ArticlePage.css";
const ArticlePage = (props) => {
const [id, setId] = useState(null);
const loadQueryParams = useCallback(() => {
setId(props.match.params.id ? props.match.params.id : null);
}, []);
useEffect(() => loadQueryParams(), [loadQueryParams]);
return (
<div>
<Header>
<div
className="article-header"
style={{ backgroundColor: "black", opacity: "0.2" }}
>
{id}
</div>
</Header>
</div>
);
};
export default ArticlePage;
If you might have an idea where this might go wrong, feel free to answer. I'm also gonna leave here how the navigationbar should look, and how it rendered.
If you need any more info or details please announce me! Thank you!
EDIT: as requested, here is a demo
I managed to solve it. The problem was that my "bootstrap.css" folder that contains my bootstrap theme was not being imported globally in "index.js", and instead it was inside "index.html".
To be noted: I was also using a Router to go to this new Component in which I was using Navbar, and since the css files weren't imported globally, the css wasn't there.

React style by class name

I'm implementing a sidebar following this example but can't figure out how to apply the styles for each className...
This is what I've tried, but there are no styles applied...
Component:
import React from 'react';
import styles from '../stylesheets/menu.css';
var Parent = React.createClass({
getInitialState(){
return {sidebarOpen: false};
},
handleViewSidebar(){
this.setState({sidebarOpen: !this.state.sidebarOpen});
},
render() {
return (
<div>
<Header onClick={this.handleViewSidebar} />
<SideBar isOpen={this.state.sidebarOpen} toggleSidebar={this.handleViewSidebar} />
<Content isOpen={this.state.sidebarOpen} />
</div>
);
}
});
var SideBar = React.createClass({
render() {
var sidebarClass = this.props.isOpen ? 'sidebar open' : 'sidebar';
return (
<div className={sidebarClass}>
<div>I slide into view</div>
<div>Me too!</div>
<div>Meee Threeeee!</div>
<button onClick={this.props.toggleSidebar} className="sidebar-toggle">Toggle Sidebar</button>
</div>
);
}
});
export default Parent;
Styles:
.sidebar {
position: absolute;
top: 60px;
}
.sidebar-toggle {
position: absolute;
top: 20%;
}
.sidebar.open {
left: 0;
}
webpack.config :
module: {
loaders: [
{
test: /\.css$/,
loader: 'css-loader'
}
]
}
Partial folder structure:
client
--stylesheets
----menu.css
--components
----Sidebar.js
You are importing the styles as an object:
import styles from '../stylesheets/menu.css';
This can be used for CSS-in-JS, but in your case it will not work.
Try changing it to:
import '../stylesheets/menu.css';
And it should correctly apply the styles.

Resources