How to change Icon on Navlink when active? - reactjs

I'm making a tab bar for phone in react js and i have icons on it. I'm using React Router to perform the routes. Right now im able to change the icon color when it is active using an .active class. Is there a way I can change the Icon File when the route is active? Here is the code attached below.
import React, { Component } from 'react';
import {NavLink} from 'react-router-dom';
import home_icon_stroke from './home_icon_stroke.svg';
import explore_icon_stroke from './explore_icon_stroke.svg';
import activity_icon_stroke from './activity_icon_stroke.svg';
import library_icon_stroke from './library_icon_stroke.svg';
import profile_icon_stroke from './profile_icon_stroke.svg';
import './Phonetabbar.css';
export default class Phonetabbar extends Component {
render() {
return (
<div className="phone-tabbar-layout" >
<div className="fixed" >
<div className="phone-tabbar-list">
<div className="tabbar-cell">
<NavLink exact to="/" >
<img src={home_icon_stroke} ></img>
</NavLink>
</div>
<div className="tabbar-cell">
<NavLink to="/explore" >
<img src={activity_icon_stroke} ></img>
</NavLink>
</div>
</div>
</div>
</div>
)
}
}

Maybe you want to try passing the isActive function to Navlink, setting a state in it.
<NavLink exact to="/"
isActive={(match, location)=>{
if(match){
//set isActive state true
}
return match;
}
>
<img src={isActive?home_icon_stroke:anotherImg} ></img>
</NavLink>

Related

How to render an animation depending on state?

I have a navbar that I need to animate using React Anime. Navbar contains Link component, which gets delay and duration as props.
Here's the code of navigation bar:
import React, {useContext, useState} from 'react'
import Link from '../Link'
import ImageLink from '../ImageLink'
import styles from './Navigation.module.css'
import { ThemeContext } from '../../theme'
let isPassed= false
export default function Navigation() {
const theme = useContext(ThemeContext)
return (
<div className={styles.root} style={{"--height-after": 6 + 'px'}}>
<div>
<ImageLink
href="/"
alt="logo"
src={theme.name === 'light' ? '/images/logo/Logo.svg' : '/images/logo/LogoBlack.svg'}
className={styles.logo}
delay={3200}
/>
</div>
<div className={styles.item}>
<Link
href="/contact"
duration={isPassed}
delay={2100}
>
Contact
</Link>
</div>
<div className={styles.item}>
<Link
href="/about"
duration={isPassed === false ? 1500 : 0}
delay={2300}
>
About us
</Link>
</div>
<div className={styles.item}>
<Link
href="/trails"
duration={isPassed === false ? 1500 : 0}
delay={2500}
>
All trails
</Link>
</div>
</div>
)
}
Here's the code of the Link component:
import React from 'react'
import styles from './Link.module.css'
import NextLink from 'next/link'
import Anime from "react-anime";
export default function Link({ href, children, className, delay, duration }) {
return (
<Anime
translateY={[-15,0]}
opacity={[0,1]}
duration={duration}
delay={delay}
>
<NextLink href={href}>
<a className={styles.link + ' ' + className}>{children}</a>
</NextLink>
</Anime>
)
}
The task is to handle the animation state, and if the animation has been already passed in the current browser session, not to animate it on page reload.
My first idea was to use sessionStorage, but then I've decided to declare a new variable isPassed in the navbar component and animate links depending on its value. So... Can I somehow change isPassed value when the animation is passed

React FontAwesome Icon disappears when I add <a> tag

I am trying to add links to my font-awesome react component.
<div>
<FontAwesomeIcon icon={faHome} size="2x" />
<div>
The component above renders the faHome icon.
But when I add anchor tag around it, it does not render. I can still see that the component in inspector tools with <svg> tag also loaded the same way when I didn't have anchor tag in the first example.
<div>
<a href="https://www.youtube.com/c/jamesqquick">
<FontAwesomeIcon icon={faHome} size="2x" />
</a>
</div>
it is working perfectly. Please check the below code:
import React from "react";
import "./styles.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faHome } from "#fortawesome/free-solid-svg-icons";
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<div>
<a href="https://www.youtube.com/">
<FontAwesomeIcon icon={faHome} size="2x" />
</a>
</div>
</div>
);
}
Here is the Code Sandbox
Here is output

react-scroll target element not found

I have a Navbar React component with a Link component which needs to scroll down to Section component when clicked. I have implemented react-scroll, however, when I click on the Link component, I get target element not found in the browser console.
The Navbar component:
import React, { Component } from "react";
import { Link, animateScroll as scroll, scroller } from "react-scroll";
class Navbar extends Component {
render() {
return (
<div>
<ul>
<li>
<Link to="section1" activeClass="active" spy={true} smooth={true}>
Section 1
</Link>
</li>
</ul>
</div>
);
}
}
export default Navbar;
And the App.js file:
import React from "react";
// Styling
import "./styles/App.css";
// Components
import Navbar from "./components/Navbar";
import SectionOne from "./components/SectionOne";
function App() {
return (
<div className="App">
<div>
<Navbar />
<SectionOne id="section1"/>
</div>
</div>
);
}
export default App;
I used this repo as a reference, however, things don't work. What have I missed here?
I have implemented a div inside of the SectionOne component
<div id="section-one-wrapper">Section One content...</div>
and then specified that id in the Link component:
<Link to="section-one-wrapper" activeClass="active" spy={true} smooth={true}>
Section 1
</Link>
and it worked.

How To Make Popup Modal Appear When Clicking a Link?

I am trying to create a Login Modal Form for an application. However, I want the popup to appear when I click a link versus a button. In other words, when I click the login link in my navbar, I don't want to be redirected to another page entirely. I just want the modal to pop up.
I'm very new to ReactJS, so I'm not sure how to go about this. Could somebody please help me understand how to get this function to work? I'd really appreciate it.
Additionally, if anyone knows of some great resources on how to implement a proper login form, I would also greatly appreciate that. I found a few on CodePen, but none of them really show a clear and approachable way on how to build this component. At least, for a beginner like me.
Located below is my code. Also, if it helps, I provided the link to the site I am currently using as a reference to build this code.
Resource: https://react-bootstrap.github.io/components/modal/
App.js
import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom'
import Navbar from './components/Navbar/navbar.js';
import Footer from './components/Footer/footer.js';
import Home from './pages/Home/home.js';
import Login from './pages/Login/login.js';
import Languages from './pages/Languages/languages.js';
function App() {
return (
<div className="App">
<BrowserRouter>
<Navbar/>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/login" component={Login}/>
<Route path="/languages" component={Languages}/>
</Switch>
</BrowserRouter>
<Footer />
</div>
);
}
export default App;
Navbar.js
import React from 'react';
import { Link } from 'react-router-dom';
import './navbar.css';
const Navbar = () => {
return (
<nav className="navbar navbar-expand-sm navbar-dark px-sm-5">
<div className="container">
<Link to='/'>
<div className="navbar-brand">
<i class="fas fa-globe fa-2x"></i>
</div>
</Link>
<ul className="navbar-nav align-items-right">
<li className="nav-item ml-5">
<Link to="/login" className="nav-link">
Log In
</Link>
</li>
<li className="nav-item ml-5">
<Link to="/signup" className="nav-link">
Sign Up
</Link>
</li>
</ul>
</div>
</nav>
)
}
export default Navbar;
Login.js
import React, { Component } from 'react';
// import { connect } from 'react-redux';
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
import './login.css';
class Login extends Component {
constructor(props, context) {
super(props, context);
this.handleShow = this.handleShow.bind(this);
this.handleClose = this.handleClose.bind(this);
this.state = {
show: false,
};
}
handleClose() {
this.setState({ show: false });
}
handleShow() {
this.setState({ show: true });
}
render() {
return (
<>
<Button variant="primary" onClick={this.handleShow}>
Launch demo modal
</Button>
<Modal show={this.state.show} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Login</Modal.Title>
</Modal.Header>
<Modal.Body>...</Modal.Body>
<Modal.Footer>
<Button variant="danger" onClick={this.handleClose}>
Cancel
</Button>
</Modal.Footer>
</Modal>
</>
);
}
}
export default Login;
Let's refactor your Navbar to be a class-component instead. We're going to need to keep track of state and pass down a binded function to the Login modal.
Additonally, it looks like you won't need a Login page anymore, so let's extract that markup so that its in a component instead. We'll call it LoginModal
Navbar.js
import React from "react"
import { Link } from 'react-router-dom';
import './navbar.css';
import LoginModal from "./components/LoginModal"
class Navbar extends React.Component{
state = {
modalOpen: false
}
handleModalOpen = () => {
this.setState((prevState) => {
return{
modalOpen: !prevState.modalOpen
}
})
}
render(){
return (
<div>
<nav className="navbar navbar-expand-sm navbar-dark px-sm-5">
<div className="container">
<Link to='/'>
<div className="navbar-brand">
<i class="fas fa-globe fa-2x"></i>
</div>
</Link>
<ul className="navbar-nav align-items-right">
<li className="nav-item ml-5">
<a onClick={this.handleModalOpen} className="nav-link">
Log In
</a>
</li>
<li className="nav-item ml-5">
<a onClick={this.handleModalOpen} className="nav-link">
Sign Up
</a>
</li>
</ul>
</div>
</nav>
<LoginModal
modalOpen={this.state.modalOpen}
handleModalOpen={this.handleModalOpen}
/>
</div>
)
}
}
export default Navbar;
Notes about Navbar:
It has a component state that keeps track of the status of the modal.
The modal is placed right at the end of nav jsx.
Replaced the Link components with standard a-tags and gave them an
onClick handler
The onClick handler, handleModalOpen toggles a value in our state
called openModal.
openModal and handleModalOpen gets passed down to the LoginModal
component.
So now let's refactor Login to be LoginModal.
LoginModal
import React from 'react';
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
import './login.css';
const LoginModal = (props) => {
return (
<>
<Modal show={props.modalOpen} onHide={props.handleModalOpen}>
<Modal.Header closeButton>
<Modal.Title>Login</Modal.Title>
</Modal.Header>
<Modal.Body>...</Modal.Body>
<Modal.Footer>
<Button variant="danger" onClick={props.handleModalOpen}>
Cancel
</Button>
</Modal.Footer>
</Modal>
</>
);
}
export default LoginModal;
Notes about LoginModal
We were able to remove a lot of the original logic now that
LoginModal is strictly just responsible for consuming props and
displaying content.
We use the prop value, props.modalOpen which is passed down from
Navbar, it gets set to true when the button is clicked inside the
Navbar component. So show={true} will display the modal
Similarly, we use another prop, props.handleModalOpen which toggles
the state in the parent component. When you call that function in the modal, it updates state.modalOpen in the parent to false.
That updated value gets passed back down to LoginModal, setting
props.modalOpen to false, so show={false} thus closing the modal.
Lastly App.js can now just be:
App.js
import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom'
import Navbar from './components/Navbar/navbar.js';
import Footer from './components/Footer/footer.js';
import Home from './pages/Home/home.js';
import Languages from './pages/Languages/languages.js';
function App() {
return (
<div className="App">
<BrowserRouter>
<Navbar/>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/languages" component={Languages}/>
</Switch>
</BrowserRouter>
<Footer />
</div>
);
}
export default App;

React Router get which `<NavLink />` is active?

I render some <NavLink /> like below
<div class="container">
<NavLink to="/" exact></NavLink>
<NavLink to="/profile"></NavLink>
<NavLink to="/message"></NavLink>
</div>
it's cool that react-router will add an active class to which is currently matched.
but how do I know which one is currently active ?
because I have some other styles to adjust based on this, like when in '/' I want to give .container 100px padding-left, and when in '/profile', I want to give .container 200px padding-left.
You can use withRouter to get the path of the current page, by using pathname you can file which is your current page.
import React from "react";
import { withRouter } from "react-router";
class Location extends React.Component {
render() {
const { match, location, history } = this.props;
return <div>You are now at {location.pathname}</div>;
}
}
const WithRouter = withRouter(ShowTheLocation);
You can add a different activeClassName to each of them.
(See https://reacttraining.com/react-router/web/api/NavLink)
For example
<div class="container">
<NavLink to="/" exact></NavLink>
<NavLink to="/profile" activeClassName="matched-profile"></NavLink>
<NavLink to="/message"></NavLink>
</div>
Then style container like this .container:has(.matched-profile)

Resources