React.js how to update reset my navbar when changing url? - javascript

I have created a navbar with items but I cannot find a way to reset the navbar when changing of URL.
NAV-item.jsx (this is where I can click on the button to make my navbar appear or disappear)
function NavItem (props) {
const [open,setOpen] = useState(false);
return(
<li className='nav-item'>
<a
className='icon-button'
onClick= {() => setOpen(!open)}>
{props.icon}
</a>
{open && props.children}
</li>
)
}
Directory.jsx (where my links are I tried to do history.push but I received an undefined error)
class Directory extends React.Component {
constructor(){
super();
this.state = {
Page1: PagesPrimaire,
Page2: PagesSecondaire
};
}
render() {
return(
<div className='menu-item'>
{
this.state.Page1.map(({id,title,linkUrl,history,match}) =>(
<Link key={id}
className='menu-item'
//to={`${linkUrl}`}
onClick = {() => history.push(this.state.Page1.linkUrl)}
>{title}</Link>
)
)
}
</div>
)
}
}
export default withRouter(Directory);
DropdownMenu.jsx (my navbar and some CSStransition tricks)
function DropdownMenu () {
const [activeMenu, setActiveMenu] = useState('main');
const DropdownItem = (props) =>
(
<a
className='menu-item'
onClick={()=>props.goToMenu && setActiveMenu(props.goToMenu)}>
{props.children}
</a>
)
return (
<div className='dropdown'>
<CSSTransition
in={activeMenu === 'main' }
unmountOnExit
timeout={500}
classNames='menu-primary'
>
<div className='menu'>
<Directory/>
<DropdownItem goToMenu='connexion'>Devenir Membre/connexion</DropdownItem>
</div>
</CSSTransition>
<CSSTransition
in={activeMenu === 'connexion' }
unmountOnExit
timeout={500}
classNames='menu-secondary'
>
<div className='menu'>
<DropdownItem goToMenu='main'><img src={Leftarrow} className='arrow' alt=''></img></DropdownItem>
</div>
</CSSTransition>
</div>
)
}
export default DropdownMenu;
Right now I can make the navbar appear and disappear by clicking a button but I cannot make it disappear when I change of Url.
Thank a lot,

as #kritiz enter a navabar for each of the route and navigate to the one you need or use the same one and use props to decide what to do there is not other way as far as I know.
the only two version I know is:
1.outside of switch
2.inside of each component with props to decied what to do in the nav

Related

React: Reset class when click on others elements

I've created an hamburger menu that change the class name when a button is click it. This works
const Hamburger = ()=> {
const [show, setShow] = useState(false);
function showIt() {
setShow(!show);
}
return (
<HamburgerIcon className={show ? 'menu-open' : ' menu-close '} onClick={showIt}>
<span></span>
</HamburgerIcon>
)
}
export default Hamburger;
Default state for the hamburger is ".menu-close" if you click toggle to ".menu-open". But when I click in a link inside the menu, the menu remain open.
What I want to achieve is to change the class also if a link in the menu is click it.
Any suggestion on what I should do here?
Thank you!!
Add the showIt function to the link inside the menu
Code:
const Hamburger = ()=> {
const [show, setShow] = useState(false);
function showIt() {
setShow(!show);
}
return (
<HamburgerIcon className={show ? 'menu-open' : ' menu-close '} onClick={showIt}>
<a href="/some/path" onClick={showIt}>
Example
</a>
</HamburgerIcon>
)
}
export default Hamburger;
You can lift the state up to the parent component.
In the example below, I've lifted the state up to the lowest common ancestor component of Menu and Hamburger components. And then passed down the state via props.
function Hamburger({ isOpen, onClick }) {
return <button onClick={onClick}>Menu {isOpen ? "↓" : "→"}</button>;
}
function Menu({ isOpen, menuItems, onClick }) {
if (!isOpen) {
return null;
}
return (
<ul>
{menuItems.map((item, index) => (
<li key={index}>
<button onClick={onClick}>{item}</button>
</li>
))}
</ul>
);
}
function App() {
const [isOpen, setIsOpen] = React.useState(false);
const handleClick = () => setIsOpen(!isOpen);
return (
<nav>
<Hamburger isOpen={isOpen} onClick={handleClick} />
<Menu
isOpen={isOpen}
onClick={handleClick}
menuItems={["Home", "About", "Contact"]}
/>
</nav>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
ul {
list-style: none;
}
<script crossorigin src="https://unpkg.com/react#18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#18/umd/react-dom.development.js"></script>
<div id="root"></div>

usestate to move component on page to a different area when clicked

I have some code:
//Top row holding one card
const Top = (props) => {
return (
<div>
<div className='row'>
<Card />
</div>
</div>
)
}
export default top;
//Bottom row of cards
const Heroes = (props) => {
return (
<div>
<p>Select a hero</p>
<div className="row">
<Card cardSize={'little-card'} hero={'Spiderman'}/>
<Card cardSize={'little-card'} hero={'Batman'}/>
<Card cardSize={'little-card'} hero={'Superman'}/>
</div>
</div>
)
}
export default Heroes;
Each card component contains a superhero. The hero prop sets the image and also serves as an identifier. There is an empty space above.
When you click one, it should move from its place to the container above, like so:
Then it when clicked again while at the top, it should move back to its original place:
Can someone dumb this down for me or show me how to do this? Code examples would be greatly appreciated.
You can add useState for checking which card gets selected, and then pass that state handling selectCard to Card component
const Heroes = (props) => {
const [selectedCard, setSelectedCard] = useState()
const selectCard = (heroName) => { setSelectedCard(heroName) }
return (
<div>
<p>Selected hero: {selectedCard}</p>
<p>Select a hero</p>
<div className="row">
<Card cardSize={'little-card'} hero={'Spiderman'} selectCard={selectCard}/>
<Card cardSize={'little-card'} hero={'Batman'} selectCard={selectCard}/>
<Card cardSize={'little-card'} hero={'Superman'} selectCard={selectCard}/>
</div>
</div>
)
}
export default Heroes;
After that, modifying your Card component like below
const Card = (props) => {
return <div onClick={() => { props.selectCard(props.hero) }}>{props.hero}</div>
}

ClickAwayListener not working with Collapse or Fade transitions

I'm trying to create a notifications area. I show a notification icon, and when the user clicks on it, I show the list of notifications.
Here's a codesandbox
The problem is that I can't mix it with ClickAwayListener.
When I use ClickAwayListener it's not shown at all.
How should I fix this?
HeaderAction.js
import Tooltip from "#material-ui/core/Tooltip";
import Fade from "#material-ui/core/Fade";
import Collapse from "#material-ui/core/Collapse";
import React, { useState } from "react";
import ClickAwayListener from "#material-ui/core/ClickAwayListener";
import Icon from "#material-ui/core/Icon";
const HeaderAction = ({ icon, title, component }) => {
const Component = component || (() => <div>NA</div>);
const [showComponent, setShowComponent] = useState(false);
const handleClick = () => {
setShowComponent(!showComponent);
};
return (
<>
<Tooltip title={title || ""}>
<div onClick={() => handleClick()}>
<Icon>{icon}</Icon>
</div>
</Tooltip>
{/* This part is not working */}
{/* <ClickAwayListener onClickAway={() => setShowComponent(false)}>
<div>
<Fade in={showComponent}>
<div>
<Component />
</div>
</Fade>
</div>
</ClickAwayListener> */}
<Fade in={showComponent}>
<div>
<Component />
</div>
</Fade>
</>
);
};
export { HeaderAction };
When you click the icon button, handleClick is called and the showComponent state is set to true, but then onClickAway from ClickAwayListener is also called and set the showComponent state to false again. The fix is simple, don't let the onClickAway handler execute by stopping the propagation after clicking the button:
<div
onClick={(e) => {
e.stopPropagation();
handleClick();
}}
>

My modal doesn't show when I click a button

Here I have my modal component. I am making an app that I want a button to open this modal that I use in multiple places like opening a preview or deleting options.
import React from 'react';
import ReactDOM from 'react-dom';
import { CSSTransition } from 'react-transition-group';
import Backdrop from '../Backdrop/Backdrop';
import '../Modal/Modal.css';
const ModalOverlay = (props) => {
const content = (
<div className={`modal ${props.className}`} style={props.style}>
<header className={`modal__header ${props.headerClass}`}>
<h2>{props.header}</h2>
</header>
<form
onSubmit={
props.onSubmit ? props.onSubmit : (event) => event.preventDefault()
}
>
<div className={`modal__content ${props.contentClass}`}>
{props.children}
</div>
<footer className={`modal__footer ${props.footerClass}`}>
{props.footer}
</footer>
</form>
</div>
);
return ReactDOM.createPortal(content, document.getElementById('modal-hook'));
};
const Modal = (props) => {
return (
<React.Fragment>
{props.show && <Backdrop onClick={props.onCancel} />}
<CSSTransition
in={props.show}
mountOnEnter
unmountOnExit
timeout={200}
classNames="modal"
>
<ModalOverlay {...props} />
</CSSTransition>
</React.Fragment>
);
};
export default Modal;
And here I use this modal for showing up deleting options.
const DocumentItem = (props) => {
const [showConfirmModal, setShowConfirmModal] = useState(false);
const showDeleteWarningHandler = () => {
setShowConfirmModal(true);
};
const calcelDeleteHandler = () => {
setShowConfirmModal(false);
};
const confirmDeleteHandler = () => {
setShowConfirmModal(false);
console.log('Delete!');
};
return (
<React.Fragment>
<Modal
show={showConfirmModal}
onCancel={calcelDeleteHandler}
header="Are you sure?"
footerClass="document-item__modal-actions"
footer={
<React.Fragment>
<Button inverse onClick={calcelDeleteHandler}>
CANCEL
</Button>
<Button danger onClick={confirmDeleteHandler}>
DELETE
</Button>
</React.Fragment>
}
>
<p>
Do you want to proceed and delete this document? Please note that it
can't be undone thereafter.
</p>
</Modal>
</React.Fragment>
);
};
I don't understand why my screen goes all black, transparent but my modal doesn't show.
How can I fix this problem?

How do I clear the the array of a state?

So this is my code :
import React from "react";
import Navigation from './Navigation';
import Foot from './Foot';
import MovieCard from './MovieCard';
class Favorites extends React.Component {
render() {
const { onSearch, favorites, favoriteCallback, totalFavorites, searchKeyUpdate } = this.props;
return (
<div>
<Navigation
onSearch={onSearch}
totalFavorites={totalFavorites}
searchKeyUpdate={searchKeyUpdate} />
<div className="container">
<button onClick={()=> this.clearFavorites(favorites)}> Clear all movies </button>
{(favorites.length < 1) ?
<h1 style={{ fontSize: '13px', textAlign: 'center' }}>Please mark some of the movies as favorites!</h1>
:
<ul
className="movies">
{favorites
.map(movie => (
<MovieCard
movie={movie}
key={movie.imdbID}
toggleFavorite={favoriteCallback}
favorites={favorites}
/>
))}
</ul>
}
<Foot />
</div>
</div>
);
}
}
const clearFavorites = (favorites) => {
this.setState({ favorites: [] });
}
The thing I need for the button to do is that when i click it that it clears the whole state of favorites. The clearFavorites function is used to clear everything but when I try this I get an error:
Why doesn't this clear the state of favorites?
You have two problems:
clearFavorites function is not in your class. So you should put it inside.
You are trying to clear the data inside the favorites array, which is not part of your state, using the function clearFavorites. So, first of all, you should add favorites array to your state and then you can manipulate the information. I suggest you to use the function getDerivedStateFromProps.
As others mentioned, first moving clearFavorites function into Favorites class.
Second, your favorites list is not part of state object, but instead you pull it out from this.props.favorites, so instead of using this.setState, we should just change the props value.
Third, since you're emptying the array, the parameter in your clearFavorites probably not needed? Please refer to below:
First we define a constructor to get the value from props and pass it to state in the constructor as below:
constructor(props) {
super(props);
this.state = {favorites: this.props.favorites}
}
clearFavorites = () => {
this.setState({favorites: []});
};
Then at last in your render method change to following:
const { onSearch, favoriteCallback, totalFavorites, searchKeyUpdate } = this.props;
const favorites = this.state.favorites;// Or in your ul tag, instead of using favorites, change it to this.state.favorites
You can try to move the clearFavorites into your component
import React from "react";
import Navigation from "./Navigation";
import Foot from "./Foot";
import MovieCard from "./MovieCard";
class Favorites extends React.Component {
render() {
const {
onSearch,
favorites,
favoriteCallback,
totalFavorites,
searchKeyUpdate
} = this.props;
return (
<div>
<Navigation
onSearch={onSearch}
totalFavorites={totalFavorites}
searchKeyUpdate={searchKeyUpdate}
/>
<div className="container">
<button onClick={() => this.clearFavorites(favorites)}>
{" "}
Clear all movies{" "}
</button>
{favorites.length < 1 ? (
<h1 style={{ fontSize: "13px", textAlign: "center" }}>
Please mark some of the movies as favorites!
</h1>
) : (
<ul className="movies">
{favorites.map(movie => (
<MovieCard
movie={movie}
key={movie.imdbID}
toggleFavorite={favoriteCallback}
favorites={favorites}
/>
))}
</ul>
)}
<Foot />
</div>
</div>
);
}
clearFavorites = favorites => {
this.setState({ favorites: [] });
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Categories

Resources