animation routes with framer motion - reactjs

Hi i try to animate 2 routes form opacity 1 to 0 on exit. But for some reason on <Link> click the routes will change(ex. '/' => '/chat?name=bob&room=here') but the page content stay the same and it wont render the component of that specific route. Also the animation is working great once i use the "Go back button" from browser.
Anyone have idea why is not working on button click?
App.js
return (
<div>
<Router>
<AnimatePresence exitBeforeEnter>
<Switch location={location} key={location.key}>
<Route path="/" exact component={Login}></Route>
<Route path="/chat" component={ChatRoom}></Route>
</Switch>
</AnimatePresence>
</Router>
</div>
);
Login.js
return (
<motion.div
initial="out"
animate="in"
exit="out"
variants={pageTransition}
className="Login-Container"
>
//same code
<Link
onClick={(event) => (!name || !room ? event.preventDefault() : null)}
to={`/chat?name=${name}&room=${room}`}
>
<button
type="submit"
className="Login-Button"
>
Sign In
</button>
</Link>
</motion.div>
);
ChatRoom.js
return (
<motion.div
initial="out"
animate="in"
exit="out"
variants={pageTransition}
className="ChatRoom-Container"
>
<div className="ChatRoom-NavBar">
<NavLink to="/">
<div
className="ChatRoom-BackButton"
style={{ backgroundImage: `url(${arrow})` }}
></div>
</NavLink>
</div>
</motion.div>
);
};

Your initial and exit prop on motion.div seem to be using the same key i.e "out" try giving the exit prop a different key. Dont forget to adjust your variants as well when you make the change.

Related

How to prevent HTML5 audio element from redirecting to the home route when clicked?

I'm working on implementing theme music into my React game. There are three routes currently, which are rendered by my 'App' component (which is wrapped by BrowserRouter) like so:
<div>
<div style={{display: 'flex', justifyContent: 'flex-end', position: 'relative', top: '2vh', right: '1vw'}}>
<Audio />
</div>
<Switch>
<Route exact path='/'>
<Menu />
</Route>
<Route path='/gameover'>
<GameOver points={totalScore} numWords={totalWords} longestWord={longestWord} tilesCleared={tilesCleared} />
</Route>
<Route path='/game/:difficulty'>
<BoardHolder />
</Route>
</Switch>
</div>
I want my 'Audio' component to be accessible from each route, which is why I have rendered it outside of my 'Switch' tags. The audio does work, and it can be accessed from every route. However, if my Audio component is clicked on from any route besides '/', it redirects the user to '/'. This is not ideal, as I would like to be able to toggle the music on/off while in the middle of a game (or at the GameOver route).
This is how my audio component is set up:
import audio from "../../Station-X.webm";
const Audio = () => {
const theme = useSelector(state => state.theme);
return (
<div
style={{
// Omitted
}}>
<button
style={{
// Omitted
}}
onClick={e => {
// Next two buttons play/pause music. Functionally speaking, they work fine.
// However, I do not want to be redirected to '/' upon a click.
// e.preventDefault() does not prevent redirect, nor does 'return false'
e.preventDefault();
document.getElementById('music-player').play()
return false;
}}>
<i className="fa-sharp fa-solid fa-volume-high"></i>
</button>
<button
style={{
// Omitted
}}
onClick={e => {
e.preventDefault();
document.getElementById('music-player').pause()
return false;
}}>
<i className="fa-sharp fa-solid fa-volume-xmark"></i>
</button>
<audio id='music-player' autoPlay loop>
<source src={audio} type="audio/mpeg" />
</audio>
</div>
);
};
I can't find a solution to this anywhere. Any insight would be appreciated.

Redux with Gatsby - wrapped Provider is not recognized

I keep encountering the error
could not find react-redux context value; please ensure the component is wrapped in a <Provider>
even though I wrapped my root file in the <Provider> already. My suspicion on what might be wrong is that instead of nested components being wrapped in the <Provider> it is a "Link" to the page that is wrapped instead?
My index.tsx file looks like this
<Provider store={reduxStore}>
<Layout>
<title>Home</title>
<div>
<Image
width="100%"
src="./app-promo1.png"
alt="app promo banner 1"
/>
<Image
width="100%"
src="./app-promo2.png"
alt="app promo banner 2"
/>
</div>
</Layout>
</Provider>
My navbar is inside a Header component which is inside the Layout component.
Layout.tsx
<div>
<LayoutWrapper>
<HeaderWrapper>
<div className="d-none d-md-block">
<Header />
</div>
<div className="d-block d-md-none">
<MobileHeader />
</div>
</HeaderWrapper>
<ContentWrapper>{children}</ContentWrapper>
<FooterWrapper>
<Footer />
</FooterWrapper>
</LayoutWrapper>
</div>
Header.tsx
<Wrapper>
<Container>
<NavWrapper>
<Logo>
<AniLink paintDrip hex="#24B2D8" to="/">
<Image src={logoImg} width="220px" alt="Logo" />
</AniLink>
</Logo>
<div className="d-flex flex-row justify-content-center align-items-center">
<AniLink paintDrip to="/shop" hex="#24B2D8">
<NavItem>Shop</NavItem>
</AniLink>
<AniLink paintDrip to="/activation" hex="#24B2D8">
<NavItem>Activation</NavItem>
</AniLink>
<AniLink cover to="/partners" bg="#24B2D8">
<NavItem>Partners</NavItem>
</AniLink>
<AniLink cover to="/support" bg="#24B2D8">
<NavItem>Support</NavItem>
</AniLink>
</div>
<Button
link="/"
text="Log in"
color="blue"
/>
</NavWrapper>
</Container>
</Wrapper>
The pages that I need the Redux/Provider in are all of these links. ie: /shop, /activation, /partner, and /support. But when I navigate from / to /shop it gives me the error.
One thing to note is that I'm using Gatsby and not create-react-app. I am not sure if there is something special that I would have to do on Gatsby or not.
Your providers need to wrap your component across your application, that's why when you change the page the context is lost. To achieve that in Gatsby, you have available the dual (gatsby-browser.js/gatsby-ssr.js) wrappRootElement API:
const React = require("react")
const { Provider } = require("react-redux")
const createStore = require("./src/state/createStore")
const store = createStore()
exports.wrapRootElement = ({ element }) => {
return (
<Provider store={store}>
{element}
</Provider>
)
}
element stands for the root React element built by Gatsby.

how to change url without adding another level of path in react router dom 5

i have an api "xyz.com/products/" and i have made an route xyz.com/products/1. This will give me an product with the id 1 . And it will render product page Component with that product details...But now on that particular product page i have an gallery of related product with their own individual "Link" to open in same product page . but when i click on any one of them ....the url changes like this "xyz.com/product/1/23" but i want only to change path like "xyz.com/products/1" --> "xyz.com/products/23"
here is my code snippets
// ///// route and link both are on App Component/////////////////
// this is the route that i have that matches xyz.com/product/1
<Route
path="/product/:id"
render={() => (
<Fragment>
<ProductContext.Provider value={{ productState, productStateDispatch }}>
<Product />
<div className={`overlay ${productState.packageSidebar}`}></div>
</ProductContext.Provider>
</Fragment>
)}
/>;
these are links will go on product page
<Row title="Our best seller">
{homeState.bestSellerProducts.map((product, index) => (
<Link
to={{
pathname: `/product/${product.id}`,
search: `type=${product.type}`,
}}
className="product-link"
key={index}
>
{" "}
<Card {...product} />
</Link>
))}
</Row>
//////////////////////////////
// this is in my product component where i have used one more component called imageGallery inside it. in which we have links////////////
{images.map((imgObj, index) => {
console.log(imgObj);
return (
<div className="item" key={index}>
<Link to={`/${imgObj.id}`} className="product-link">
<div className="img">
<img
height={100}
width={100}
src={imgObj.product_image}
alt="product-img"
/>
</div>
</Link>
</div>
);
})}
// i know i messing in routing i hope will get solution.... i just want that when i click on any link in this imageGallery component .it should be open inside same product page in which i m already present.. thats it
Including exact keyword in the Route component might solve your problem, try out!, demo example:
<Route exact to='/' component={home} />

admin-on-rest toggle menu (show / hide)

I'm using admin-on-rest in my react application as admin interface.
My problem is the menu, I'm add a DashboardMenuItem to toggle (show/hide) the menu. But I have no idea what the onClick function should look like and I find no example of this in the documentary or somewhere else.
Can anyone help me by giving an example for this?
My Code:
const Menu = ({ hasDashboard, onMenuTap, resources, translate, logout }) => (
<div style={styles.main}>
<WithPermission value='ROLE_SA'>
{hasDashboard && <DashboardMenuItem onClick={onMenuTap} />}
</WithPermission>
{resources
.filter(r => r.list)
.map(resource => (
<MenuItemLink
key={resource.name}
to={`/${resource.name}`}
primaryText={translatedResourceName(resource, translate)}
leftIcon={<resource.icon />}
onClick={onMenuTap}
/>
))}
{/* <MenuItemLink primaryText='Reports' key='reports' to={`/reports`} leftIcon={<UserIcon />} onClick={onMenuTap} /> */}
<WithPermission value='ROLE_SA'>
<SelectField floatingLabelText='Language for Datasets' onChange={LocaleSwitcher}>
<MenuItem value={'de'} primaryText='DE' />
<MenuItem value={'en'} primaryText='EN' />
</SelectField>
</WithPermission>
{logout}
<img src={Logo} style={{maxWidth: '100%', margin: '0 auto'}} />
</div>
)

Prop to detect if link is active in react

I have a NavLink which have child components
<NavLink
className={StyledAppNavItem}
activeClassName={StyledAppNavItemActive}
to={link.path}
>
<Icon size={28} icon={link.icon} color={isActive?'red':'blue'}/>
<StyledAppNavName>{link.name}</StyledAppNavName>
</NavLink>
Like activeClassName is attached when the link is active, I need to detect if this link is active and send a prop to its child component Icon
Somewhat like <Icon color={linkisActive?'red':'blue'}/>
Unfortunately, there is no way to get isActive from NavLink. You need to create your custom NavLink. Something like this:
function MyNavLink() {
return (
<Route path={link.path} children={({ match }) => (
<Link
className={`${StyledAppNavItem} ${match ? StyledAppNavItemActive : ''}`}
to={link.path}
>
<Icon size={28} icon={link.icon} color={match ? 'red' : 'blue'}/>
<StyledAppNavName>{link.name}</StyledAppNavName>
</Link>
)} />
);
}
Or you can just add Route to your current component:
<NavLink
className={StyledAppNavItem}
activeClassName={StyledAppNavItemActive}
to={link.path}
>
<Route path={link.path} children={({ match }) => (
<Icon size={28} icon={link.icon} color={match?'red':'blue'}/>
)} />
<StyledAppNavName>{link.name}</StyledAppNavName>
</NavLink>

Resources