React cannot read property '' of undefined - javascript

please im having issue rendering dynamic data in my react ProductScreen.js
Note,... the data rendered well in Product.js but same data isnt render in the ProductScreen.js because the ProductScreen.js link is rendered via the "id"
Thanks
App.js
import './App.css';
import { useState, useEffect } from 'react';
import { BrowserRouter as Router, Switch, Route} from 'react-router-dom';
//Screens
import HomeScreen from './screens/HomeScreen';
import ProductScreen from './screens/ProductScreen';
import CartScreen from './screens/CartScreen';
//components
import Navbar from './components/Navbar'
import Backdrop from './components/Backdrop'
import SideDrawer from './components/SideDrawer'
import AddProductScreen from './screens/AddProductScreen';
import data from './data'
function App() {
const { products } = data;
const [sideToggle, setSideToggle] = useState(false)
const [cartItems, setCartItem] = useState([])
const onAdd = (product) =>{
const exist = cartItems.find(item => item.id === product.id)
if (exist) {
setCartItem(cartItems.map(item => item.id === product.id ? {...exist, qty: exist.qty + 1} : item ))
} else{
setCartItem([...cartItems, {...product, qty: 1}])
}
}
const onRemove =(product) =>{
}
return (
<Router>
<Navbar countCartItems={cartItems.length} click={() => setSideToggle(true)}/>
<Backdrop show={sideToggle} click={() => setSideToggle(false)} />
<SideDrawer show={sideToggle} click={() => setSideToggle(false)} />
{/* <HomeScreen products={ products } onAdd={ onAdd }/> */}
{/* <CartScreen onRemove={onRemove} onAdd={onAdd} cartItems={cartItems}/> */}
{products.map(product => (
<h1></h1>
))}
<main>
<Switch>
<Route exact path="/" > <HomeScreen products={ products } onAdd={ onAdd }/> </Route>
<Route exact path="/cart" > <CartScreen cartItems={cartItems} onRemove={ onRemove } onAdd={ onAdd }/>
</Route>
<Route exact path="/product/:id" > <ProductScreen cartItems={cartItems} onAdd={ onAdd }/> products={products} </Route>
<Route exact path="/add" component={AddProductScreen} />
</Switch>
</main>
</Router>
);
}
export default App;
HomeScreen.js
import './HomeScreen.css';
import Product from '../components/Product'
import { useEffect } from 'react';
// import data from '../data'
const HomeScreen = ({ onAdd, products }) => {
// const { products } = data;
return (
<div className="homescreen">
<h1 className="homescreen_title">Latest Products</h1>
<div className="homescreen_products">
{products.map(product => (
<Product key={ product.id } product={ product } onAdd={ onAdd }/>
)) }
</div>
</div>
)
}
export default HomeScreen
ProductScreen.js
import './ProductScreen.css';
const ProductScreen = ({ products }) => {
return (
<div className="productscreen">
<div className="productscreen__left">
<div className="left__image">
<img className="small" src={products.image} alt={product.name} />
</div>
<div className="left__info">
<p className="left__name">{products.name}</p>
<p >${products.price}</p>
<p >${products.descrption}</p>
</div>
</div>
)
}
export default ProductScreen
Product.js
import React from 'react'
import { Link } from 'react-router-dom'
const Product = ({ product, onAdd }) => {
return (
<div>
<img className="small" src={product.image} alt={product.name} />
<h3>{product.name}</h3>
<div>${product.price}</div>
<div>
<button onClick={()=> onAdd(product)}> Add To Cart</button>
<button > <Link to={`/product/${product.id}`}>Features</Link></button>
</div>
</div>
)
}
export default Product

The problem is that you are sending the items to ProductsScreen as cartItems <ProductScreen cartItems = {cartItems} onAdd = {onAdd} /> but you are calling the product property that does not exist const ProductScreen = ({product}) => {}

Related

useParam is not working in react router Dom v6?

I am trying to pass a parameter to my other component which is productDetail component but when I am trying to access that parameter value using useParam it doesn't seems to work:
App:
import React from "react";
import { Route, Routes } from "react-router-dom";
import MainHeader from "./components/MainHeader.jsx";
import Product from "./pages/Product.jsx";
import ProductDetails from "./pages/ProductDetails.jsx";
import Welcome from "./pages/Welcome.jsx";
const App = () => {
return (
<div style={{ textAlign: "center" }}>
<header>
<MainHeader />
</header>
<Routes>
<Route path="/welcome" element={<Welcome />} />
<Route path="/product" element={<Product />} />
<Route path="/products/:productId" element={<ProductDetails />} />
</Routes>
</div>
);
};
export default App;
ProductDetailes:
import React from "react";
import { useParams } from "react-router-dom";
const ProductDetails = () => {
const params = useParams;
console.log(params.productId);
return (
<div>
<h1>Product Detail</h1>
<p>{params.productId}</p>
</div>
);
};
export default ProductDetails;
The useParams hook is a function and actually needs to be invoked in order to have any effect.
Example:
const ProductDetails = () => {
const { productId } = useParams();
useEffect(() => {
console.log({ productId });
}, [productId]);
return (
<div>
<h1>Product Detail</h1>
<p>{productId}</p>
</div>
);
};

How to have multipage in react while getting the same function for navbar?

I can create multipage but copying the navbar in every shopping page feels redundant plus I want each page can share one cart function from navbar when I click the add to cart(from shopping page).
I can do this but it becomes one single page react.
Menmain, Women, Kids are shopping page which imported to the Navbar page. Using the props I can get the function for navbar to enable the cart function on each shopping page. But by doing this.. I only get one single page.
In short, How to make my navbar a links to one another and function as one cart to all ... like a parent.
As of now these code are in single page react..
Index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import NavbarShop from "./NavbarShop";
import Home from "./Home";
import Menmain from './Components/MenShop/menmain'
import Women from './Components/WomenShop/Women'
import Kids from './Components/KidsShop/Kids'
import Footer from "./Footer";
ReactDOM.render(
<Router>
<NavbarShop/>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/menmain" element={<Menmain />} />
<Route path="/Women" element={<Women />} />
<Route path="/Kids" element={<Kids />} />
</Routes>
<Footer/>
</Router>,
document.getElementById("root")
);
NavbarShop.jsx
import "./App.css";
import Mainlogo from "./Components/Assets/urban-fit-logo.png"
import 'bootstrap/dist/css/bootstrap.min.css';
import { Navbar, Nav, Container} from 'react-bootstrap';
import Offcanvas from 'react-bootstrap/Offcanvas'
import Basket from './Components/Basket';
import { useState } from 'react';
import Menmain from './Components/MenShop/menmain'
import Data from './Components/Data/data';
import Data2 from './Components/Data/data2';
import Women from './Components/WomenShop/Women';
import Data3 from './Components/Data/data3';
import Kids from './Components/KidsShop/Kids';
import Home from "./Home";
export default function NavbarShop() {
const { product } = Data
const { Fproducts } = Data2;
const { Kproduct } = Data3;
const [ cartItems, setCartItems] = useState([]);
const countCartItems = cartItems.length
const onAdd = (product) => {
const exist = cartItems.find((x) => x.id === product.id);
if (exist) {
setCartItems(
cartItems.map((x) =>
x.id === product.id ? { ...exist, qty: exist.qty + 1 } : x
)
);
} else {
setCartItems([...cartItems, { ...product, qty: 1 }]);
}
};
const onRemove = (product) => {
const exist = cartItems.find((x) => x.id === product.id);
if (exist.qty === 1) {
setCartItems(cartItems.filter((x) => x.id !== product.id));
} else {
setCartItems(
cartItems.map((x) =>
x.id === product.id ? { ...exist, qty: exist.qty - 1 } : x
)
);
}
};
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div className='app'>
<div className='navbar-container'>
<Navbar collapseOnSelect expand="lg" bg="white" text="black" fixed="top" className="navbar-bootstrap">
<Container>
<Navbar.Brand href="#home" className="navLogo">
<div>
<img src={Mainlogo} alt="main-logo" className='main-logo'></img>
</div>
</Navbar.Brand>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto">
<Nav.Link href="/" className="navlink">Home</Nav.Link>
<Nav.Link href="Shopmen" className="navlink">Shop Men</Nav.Link>
<Nav.Link href="Shopwomen" className="navlink">Shop Women</Nav.Link>
<Nav.Link href="Shopkids" className="navlink">Shop Kids</Nav.Link>
</Nav>
<Nav>
<Nav.Link className="nav-a" onClick={handleShow} id="badge">
Cart{' '}
{countCartItems ? (
<p className="badge">{countCartItems}</p>
) : (
''
)}
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
<Offcanvas show={show} onHide={handleClose} placement='end' className="cart-container">
<Offcanvas.Header closeButton className="cartHeader">
<Offcanvas.Title className="cartName">CART</Offcanvas.Title>
</Offcanvas.Header>
<Offcanvas.Body>
<Basket
cartItems={cartItems}
onAdd={onAdd}
onRemove={onRemove}
></Basket>
</Offcanvas.Body>
</Offcanvas>
</div>
<div className='men-clothing'>
<Home/>
<Menmain product= { product } onAdd={onAdd} onRemove={onRemove}></Menmain>
<Women product= { Fproducts } onAdd={onAdd} onRemove={onRemove}></Women>
<Kids product= { Kproduct } onAdd={onAdd} onRemove={onRemove}></Kids>
</div>
</div>
);
}

React : How to make my SearchBar render in another Page?

I have 2 pages both are childrens from App.
_ NavbarComp.js
_ Home.js
Right now I have a functionnal SearchBar in my Home, I'd like to pass the values between NavbarComp & Home.
When I search from my NavbarComp, I'd like to have a render only on the Home page.
This is what it looks like so far.
I now need to remove my input button from Home, and pass the values between both pages Navbar & Home.
I dont think I can use props there, tho.. looking for solutions !
NavbarComp.js
import { Layout } from "antd";
import { Link, useHistory } from "react-router-dom";
import Cookies from "js-cookie";
import { useDispatch } from "react-redux";
import { logout } from "redux/auth/authActions";
import { Nav, Navbar, NavDropdown, Form, FormControl, Button, Row, Col, Container } from "react-bootstrap";
const { Header } = Layout;
export const NavbarComp = ({input, setInput}) => {
const history = useHistory();
const cookie = Cookies.get('token');
const dispatch = useDispatch();
const logMeOut = (e) => {
e.preventDefault();
dispatch(logout());
history.push('/');
}
return (
<>
<Navbar bg="light" expand="lg">
<Form className="d-flex">
<FormControl
type="search"
placeholder="Search"
className="mr-2"
aria-label="Search"
input={input}
/>
</Navar>
</>
)
}
Home.js
import React from 'react';
import { Link } from "react-router-dom";
import { useSelector } from 'react-redux';
import { v4 as uuid_v4 } from "uuid";
export const Home = () => {
const connected = useSelector(state => state.auth.user)
const [input, setInput] = React.useState('');
const [flats, setFlats] = React.useState([]);
const [flatsDefault, setFlatsDefault] = React.useState([]);
React.useEffect(() => {
getListing('real_estates')
}, [])
const getListing = async (url) => {
const config = {
method: 'GET',
};
const response = await fetch(`${process.env.REACT_APP_API_URL}/${url}`, config);
const data = await response.json();
setFlats(data)
setFlatsDefault(data)
};
const updateInput = async (input) => {
const filtered = flatsDefault.filter(flat => {
return flat.title.toLowerCase().includes(input.toLowerCase())
})
setInput(input);
setFlats(filtered);
}
return (
<>
<input
type='text'
input={input}
placeholder={"Search for properties"}
onChange={(e) => updateInput(e.target.value)}
/>
<div className="home-header">
<div className="bg-img-desc">
<h1>List of real estates</h1>
</div>
</div>
<div className="container" style={{ padding: '0 3.5rem' }}>
<ul className="row">
{flats ? (
flats.map(flat => (
<li className="col-12 col-sm-6 col-md-4 col-lg-3 mb-4" key={uuid_v4()}>
<div className="card h-100">
{ flat.images_url && <img src={`${process.env.REACT_APP_API_URL}${flat.images_url[0]}`} className="card-img-top" alt=""/> }
<div className="card-body">
<h5>{flat.title}</h5>
<p>Price : {flat.price} €</p>
<p>location : {flat.location}</p>
{connected && <Link to={`/real_estates/${flat.id}`} className="btn btn-primary">Details</Link>}
</div>
</div>
</li>
))
) : (
<h2>Loading...</h2>
)}
</ul>
</div>
</>)
}
App.js
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Layout } from 'antd';
import { NavbarComp } from "components/NavbarComp";
import { Home } from "pages/Home";
import Realestate from "pages/Realestate";
import NewRealestate from "pages/NewRealestate";
import { Other } from "pages/Other";
import { Login } from "pages/Login";
import { Register } from "pages/Register";
import Profile from "pages/Profile";
import { useDispatch, useSelector } from 'react-redux';
import { getUser } from 'redux/auth/authActions';
import Cookies from 'js-cookie';
function App() {
const dispatch = useDispatch();
const user = useSelector(state => state.auth.user);
React.useEffect(() => {
dispatch(getUser(Cookies.get('id')))
console.log(user)
}, [])
return (
<Layout className="layout" style={{ backgroundColor: 'transparent' }}>
<Router>
<NavbarComp />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route exact path="/real_estates/:id">
<Realestate />
</Route>
<Route path="/new_real_estate">
<NewRealestate />
</Route>
<Route path="/other">
<Other />
</Route>
<Route exact path="/login" >
<Login />
</Route>
<Route exact path="/register" >
<Register />
</Route>
<Route exact path="/profile" >
<Profile user={user} />
</Route>
</Switch>
</Router>
</Layout>
);
}
export default App;
I can see three ways that you can implement to resolve this.
The first one is creating a context, so your state is going to be share through all your app. So when you change it inside your NavbarComp you will be able to get this value in another component.
The second one is similar to context but using redux. I saw that you are using redux in your project, you can share those values through redux.
The other way is to create a useState() inside your app component and pass it as props to your NavbarComp and your home. So this state will be shared between those two.
function App() {
const dispatch = useDispatch();
const user = useSelector(state => state.auth.user);
const [value, setValue] = useState()
React.useEffect(() => {
dispatch(getUser(Cookies.get('id')))
console.log(user)
}, [])
return (
<Layout className="layout" style={{ backgroundColor: 'transparent' }}>
<Router>
<NavbarComp value={value} setValue={setValue}/>
<Switch>
<Route exact path="/">
<Home value={value} setValue={setValue}/>
</Route>
<Route exact path="/real_estates/:id">
<Realestate />
</Route>
<Route path="/new_real_estate">
<NewRealestate />
</Route>
<Route path="/other">
<Other />
</Route>
<Route exact path="/login" >
<Login />
</Route>
<Route exact path="/register" >
<Register />
</Route>
<Route exact path="/profile" >
<Profile user={user} />
</Route>
</Switch>
</Router>
</Layout>
);
}
export default App;

React-router Route not rendering component

I'm trying to use react router in the following code, and render the RecipeCardDetail component. URL changes but nothing renders. It just renders when I click URL and press enter. I'm trying to show recipeId (URL Parameter) in the RecipeCardDetail component. I would like some help if possible.
Below my components.
App.js
import React, { useEffect, useState } from 'react';
import './App.css';
import RecipeCard from './components/RecipeCard/RecipeCard';
import RecipeCardDetail from "./components/RecipeCardDetail/RecipeCardDetail"
import Form from './components/Form/Form';
import axios from 'axios';
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
function App() {
const [recipes, setRecipes] = useState([])
const [filter, setFilter] = useState("")
const [query, setQuery] = useState("")
useEffect(() => {
getRecipe()
}, [query])
const getRecipe = () => {
const key = process.env.REACT_APP_RECIPE_SEARCH_APP_API_KEY
const id = process.env.REACT_APP_RECIPE_SEARCH_APP_ID
axios.get(`https://api.edamam.com/api/recipes/v2?type=public&q=${query}&app_id=${id}&app_key=${key}`)
.then(response => {
console.log(response.data.hits)
setRecipes(response.data.hits)
})
.catch(error => {
console.log(error)
})
}
return (
<Router>
<div className="App">
<div className="container">
<Form setFilter={setFilter} setQuery={setQuery} filter={filter} />
<div className="row">
<Switch>
<Route exact path="/" >
{recipes.map((item, id) => {
return <RecipeCard key={id} img={item.recipe.image} title={item.recipe.label} ingredients={item.recipe.ingredientLines} recipeId={id} />
})}
</Route>
<Route path="/recipe-card-detail/:recipeId" >
<RecipeCardDetail />
</Route>
</Switch>
</div>
</div>
</div>
</Router>
);
}
export default App;
RecipeCard.js
import React from 'react'
import "./style.css"
import "../../../node_modules/bootstrap/dist/css/bootstrap.min.css"
import { BrowserRouter as Router, Link } from "react-router-dom"
function RecipeCard( { img, title, ingredients, recipeId } ) {
return (
<Router>
<div className="col-xl-4 col-md-6 col-s-12">
<div className="card mt-5" style={{ width: "24rem" }}>
<img src={img} className="card-img-top" alt="img" />
<div className="card-body">
<h3 className="text align">{title}</h3>
<ul className="card-text">
{ingredients.map((item, id) => {
return <li key={id} >{item}</li>
})}
</ul>
<Link to={`/recipe-card-detail/${recipeId}`}>Details</Link>
</div>
</div>
</div>
</Router>
)
}
export default RecipeCard
Try changing the order in which you are defining the routes.
<Switch>
<Route path="/recipe-card-detail/:recipeId" >
<RecipeCardDetail />
</Route>
<Route exact path="/" >
{recipes.map((item, id) => {
return <RecipeCard key={id} img={item.recipe.image} title={item.recipe.label} ingredients={item.recipe.ingredientLines} recipeId={id} />
})}
</Route>
</Switch>

Why is react-transition-group not calling componentWillEnter nor componentWillLeave on route change?

I am following this hackernoon guide https://hackernoon.com/animated-page-transitions-with-react-router-4-reacttransitiongroup-and-animated-1ca17bd97a1a in order to apply enter and leave animations to my react components when a route changes. I have obviously adapted the code to fit my site, and have decided not to use Animated but rather just pure CSS. Right now I'm just testing the code with console.log statements, and I noticed that componentWillEnter and componentWillLeave are not being called on route changes. Also, componentWillAppear only gets called once.
Here is the relevant code for each component, including App.js and index.js:
Animated Wrapper:
import React, {Component} from "react";
import styles from '../styles/AnimatedWrapper.css';
const AnimatedWrapper = WrappedComponent =>
class AnimatedWrapper extends Component {
componentWillAppear(cb) {
console.log('componentWillAppear');
cb();
}
componentWillEnter(cb) {
console.log('componentWillEnter');
cb();
}
componentWillLeave(cb) {
console.log('componentWillLeave');
cb();
}
render() {
return (
<div id="animated-wrapper" className={styles.animatedPageWrapper}>
<WrappedComponent {...this.props}/>
</div>
);}
};
export default AnimatedWrapper;
App.js:
import React, { Component } from 'react';
import { Route, Switch } from 'react-router-dom';
import TransitionGroup from "react-transition-group/TransitionGroup";
import Navbar from "./components/Navbar";
import Footer from "./components/Footer";
import Slider from "./components/Slider";
import ComingSoon from "./components/ComingSoon";
const firstChild = props => {
const childrenArray = React.Children.toArray(props.children);
return childrenArray[0] || null;
}
class App extends Component {
render() {
return (
<div className="App">
<Navbar />
<Switch>
<Route
path="/coming-soon"
children={({ match, ...rest }) => (
<TransitionGroup component={firstChild}>
{match && <ComingSoon {...rest} />}
</TransitionGroup>
)}/>
<Route
path="/"
children={({ match, ...rest }) => (
<TransitionGroup component={firstChild}>
{match && <Slider {...rest} />}
</TransitionGroup>
)}/>
</Switch>
<Footer />
</div>
);
}
}
export default App;
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import './index.css';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
Slider.js:
import React, { Component } from 'react';
import _ from 'lodash';
// components
import AnimatedWrapper from './AnimatedWrapper';
import Separator from './Separator';
// styles
import styles from '../styles/Slider.css';
// images
import Apartment from "../../public/images/apartment.jpg";
import Floor from "../../public/images/floor.jpg";
import Furniture from "../../public/images/furniture.jpg";
import Kitchen1 from "../../public/images/kitchen.jpg";
import Kitchen2 from "../../public/images/kitchen-2.jpg";
class SliderComponent extends Component {
constructor(props) {
super(props);
this.state = {
currentSlide: 0,
slides: [Apartment, Floor, Furniture, Kitchen1, Kitchen2]
};
}
componentDidMount() {
this.zoomAnimation();
this.slideContentAnimation();
this.sliderInterval = setInterval(() => {
if (this.state.currentSlide === 4) {
if (this.refs.slider) {
this.setState({ currentSlide: 0 });
}
} else {
if (this.refs.slider) {
this.setState({ currentSlide: this.state.currentSlide + 1 });
}
}
}, 6000);
}
componentWillUpdate() {
const currentContent = document.getElementById(`content-${this.state.currentSlide}`);
setTimeout(() => {
currentContent.classList.remove(`${styles.currentContent}`);
}, 1500);
}
componentDidUpdate() {
this.zoomAnimation();
this.slideContentAnimation();
}
setSlide(number) {
this.setState({ currentSlide: number });
}
zoomAnimation() {
setTimeout(() => {
const currentSlide = document.getElementById(`slide-${this.state.currentSlide}`);
currentSlide.classList.add(`${styles.slideZoom}`);
}, 500);
}
slideContentAnimation() {
setTimeout(() => {
const currentContent = document.getElementById(`content-${this.state.currentSlide}`);
if (currentContent) {
currentContent.classList.add(`${styles.currentContent}`);
}
}, 1500);
}
renderSlides() {
return this.state.slides.map((slide, index) => {
const isCurrent = index === this.state.currentSlide;
const slideStyle = {
backgroundImage: `url(${this.state.slides[index]})`
}
return (
<div
id={`slide-${index}`}
key={`slide-${index}`}
className={`
${styles.slide}
${isCurrent ? styles.currentSlide : null}
`}
style={slideStyle}
alt="slide">
<div
id={`content-${index}`}
key={`content-${index}`}
className={`
${styles.content}
`}>
<h1>{`WE SPECIALIZE IN KITCHENS ${index}`}</h1>
<Separator
containerWidth={720}
circleWidth={5}
circleHeight={5}
backgroundColor="#fff"
lineWidth={350}
lineColor="#fff"
/>
<div
className={`${styles['hvr-sweep-to-top']} ${styles.btn}`}>
More Information
</div>
</div>
</div>
);
});
}
renderNavBar() {
return (
<div className={styles.sliderNav}>
{_.range(5).map((index) => {
return (
<div
key={index}
onClick={() => this.setSlide(index)}
className={this.state.currentSlide === index ? styles.current : null}>
</div>
)
})}
</div>
)
}
render() {
return (
<div className={styles.container} ref="slider">
<div className={styles.slidesContainer}>
{this.renderSlides()}
</div>
{this.renderNavBar()}
</div>
);
}
}
const Slider = AnimatedWrapper(SliderComponent);
export default Slider;
ComingSoon.js:
import React from 'react';
import AnimatedWrapper from './AnimatedWrapper';
import styles from '../styles/ComingSoon.css';
const ComingSoonComponent = function() {
return (
<div>
<div className={styles.mainContent}>
<div>
<h1 className={styles.mainTitle}>{`Coming Soon`}</h1>
</div>
</div>
</div>
);
};
const ComingSoon = AnimatedWrapper(ComingSoonComponent);
export default ComingSoon;
Try to Use react-transition-group, it will be help.
You can use it like this Example. As follow main code:
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom'
import { CSSTransition, TransitionGroup } from 'react-transition-group'
const PageFade = (props) => (
<CSSTransition
{...props}
classNames="fadeTranslate"
timeout={1000}
mountOnEnter={true}
unmountOnExit={true}
/>
)
const Layout = ({ children }) => (
<section>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Non existing</Link></li>
</ul>
</nav>
<hr />
{children}
</section>
)
const App = (props) => {
const locationKey = props.location.pathname
return (
<Layout>
<TransitionGroup>
<PageFade key={locationKey}>
<section className="fix-container">
<Switch location={props.location}>
<Route exact path="/" component={Home} />
<Route exact path="/about" component={About} />
<Route component={NotFound} />
</Switch>
</section>
</PageFade>
</TransitionGroup>
</Layout>
)
}
const BasicExample = () => (
<BrowserRouter>
<Route path="/" component={App} />
</BrowserRouter>
);
render(<BasicExample />, document.getElementById('root'));

Categories

Resources