I have a container which can possible display several child containers based on state. When the state changes (based on a button click), I would like:
The current container to fade out
The height of the main container to animate to the be the height of its new child container
The new child container to fade in
I feel like I'm on the right track with my demo, but the AnimatePresence seems to be ignored as none of the opacity animations are working. I'm hoping someone can please take a look and let me know what I need to adjust?
https://codesandbox.io/s/animating-shared-layouts-with-content-changing-h8hvq?file=/src/App.js
function Home() {
return (
<div>
<div className="row" />
<div className="row" />
</div>
);
}
function Contact() {
return (
<div>
<div className="row" />
<div className="row" />
<div className="row" />
<div className="row" />
<div className="row" />
</div>
);
}
const sections = {
home: "Home",
contact: "Contact"
};
export default function App() {
const [activeSection, setActiveSection] = useState(sections.home);
return (
<div className="outer-container">
<AnimateSharedLayout>
<motion.div layout initial={{ borderRadius: 25 }}>
<h3>Text on top</h3>
<AnimatePresence key={activeSection} exitBeforeEnter initial={false}>
<motion.div
initial={{ opacity: 0 }}
animate={{
opacity: 1,
transition: { delay: 1.2, duration: 1 }
}}
exit={{
opacity: 0,
transition: { delay: 0, duration: 1 }
}}
>
<div className="inner-container">
<div className="content">
<div className="avatar" />
{activeSection === sections.home && <Home />}
{activeSection === sections.contact && <Contact />}
</div>
</div>
</motion.div>
</AnimatePresence>
</motion.div>
</AnimateSharedLayout>
<button
type="button"
onClick={() =>
setActiveSection(
activeSection === sections.home ? sections.contact : sections.home
)
}
>
Go to {activeSection === sections.home ? "Contact" : "Home"} section
</button>
</div>
);
}
Related
function App() {
const [people, setPeople] = useState([
{
name: "Model Baby",
url:"https://www.themodelskit.co.uk/wp-
content/uploads/2021/10/shutterstock_1431963185.jpg"
},
{
name: "Seema Jaswal",
url:"https://static.standard.co.uk/2021/06/14/16/euro_2020_live_seema_jaswal_01-1.jpg?
width=968&auto=webp&quality=50&crop=968%3A645%2Csmart"
},
{
name: 'Plaboi Baby',
url: '../assets/IMG_20210811_105110_849.webp'
}
]);
const [per, setPer] = useState(people.name);
return (
<div className="app">
I am try to update my sidebar from the data above, i am trying to track changes in my sidebar from the main app, how do i effectively deploy useState or context API for this purpose
<Routes>
<Route path='/explore' element={<>
<div className='app__tinder'>
<TinderCards people={people} setPer={setPer} />
<SwipeButtons />
</div>
<aside className='app__sidebar right'>
<RightSidebar per={per} />
</aside>
</div>
</div>
</>} />
</div>
);
}
export default App;
TinderCard.js i need the name and age here to update on the sidebar when it changes
function TinderCards({people, setPer}) {
return (
<div>
<div className='tinderCards__cardContainer'>
{people.map((person) => (
<TinderCard className="swipe" key={person.name} preventSwipe={["up, down"]} onClick=
{() => {setPer(person.name)}} >
<div className='card' style={{ backgroundImage: `url(${person.url})`}}>
<h3>{person.name}</h3>
</div>
</TinderCard>
))}
</div>
</div>
)
}
export default TinderCards
RightSidebar, i tried applying useState but i am not sure that i am using it properly, pls help
function RightSidebar({per}) {
console.log("move", per)
return (
<div className='rightSidebar'>
{/* {people.map((person) => ( */}
<div className='rightSidebar__contents'>
<h1>About</h1>
<Card className='rightSidebar__card'>
<div className='card__nameContents'>
<CardHeader className='card__nameAge' title = {per.name} subheader =
{per.age} avatar =
{<VerifiedIcon className='activeIcon verified' />} />
<CardHeader className='card__active' title = "active" avatar=
{<FiberManualRecordIcon className='activeIcon' />} />
</div>
I have the following code for a button in my ReactApp to open a new window with specific size:
<button
type="button"
style={{ height: '20px', width: '50px' }}
className="btn btn-primary"
onClick={() => {
window.open(
"",
"Popup",
"width=975, height=92, top=30"
);
}}
/>
I want to load another component when user clicks on the button. How can I achieve that? I have tried to load the component and then use it like the following, but didn't work:
import component from "./component"
<button
type="button"
style={{ height: '20px', width: '50px' }}
className="btn btn-primary"
onClick={() => {
window.open(
"{<component />}",
"Popup",
"width=975, height=92, top=30"
);
}}
/>
What would be the best way to do this?
Here is my component:
export default function component(props) {
return (
<div className="container">
<div className="cabinet"><img src={image} />
<div className="devices"> <img src={image2} />
</div>
</div>
);
}
Add a state in main page and pass it to component
const [open, setOpen] = useState[false];
const onClickHandle = () => {
setOpen(true);
};
return (
<>
<button
type="button"
style={{ height: '20px', width: '50px' }}
className="btn btn-primary"
onClick={onClickHandle}
/>
<component open={open} />
</>
);
Add a new props to control the component
export default function component(props) {
const { open } = props;
return (
<>
{open && (
<div className="container">
<div className="cabinet">
<img src={image} />
<div className="devices">
{' '}
<img src={image2} />
</div>
</div>
</div>
)}
</>
);
}
Using state hooks and conditional rendering, you can load a react component on a button onClick.
const [visible, setVisible] = React.useState(false);
function click(e) {
e.preventDefault();
setVisible(true);
}
return (
<div>
<button onClick={(event) => {
click(event)
}} />
{isVisible && (
<YourComponent />
)
}
</div>
)
I'm working on a billing app. I have managed to fetch the Products from an API..... But now I'm trying to use useParams() to navigate to random pages that would display the items according to the ID by pressing a button...the navigation works fine but it wont display the data of that passed ID, it displays all the data in my API.
I would really appreciate some help or feedback, Thanks !
Item.js:
import React, { useEffect } from "react";
import { connect } from "react-redux";
import { getItems } from "../store/actions/itemsActions";
import { Link } from "react-router-dom";
import "./Items.css";
function Items({ getItems, items }) {
useEffect(() => {
getItems();
}, []);
function getRandomElFromArray(items) {
return Math.floor(Math.random() * items);
}
return (
<div>
<div className="container">
<div
className="image"
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: 200,
width: 100,
}}
>
<img src="http://i.stack.imgur.com/yZlqh.png" alt="" />
</div>
</div>
<div>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<div className="item-preview">
{items &&
items.items &&
items.items.map((item) => (
<div key={item.id}>
<h4>
ID:<Link to={`/bills/${item.id}`}> {item.id}
<button className="button4">Analyse Receipt</button>
</Link>
</h4>
</div>
))}
</div>
</div>
</div>
</div>
);
}
const mapStateToProps = (state) => {
return {
items: state.items,
};
};
const mapDispatchToProps = (dispatch) => {
return {
getItems: () => dispatch(getItems()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Items);
Billing.js:
import React, { useState } from "react";
import "./Bill.css";
import { Link, useParams, Switch, Route } from "react-router-dom";
import { connect } from "react-redux";
import { getItems } from "../store/actions/itemsActions";
function BillList({ items }) {
const [counter, setCounter] = useState(1);
const { id } = useParams();
function Display(props) {
return <label style={{ marginLeft: ".5rem" }}>{props.message}</label>;
}
return (
<div className="bills">
<div className="explore-container">
{items &&
items.items &&
items.items.filter((item) => item.id === id)
.map((item) => (
<div className="item-list" key={item.id}>
<h2>Title: {item.title}</h2>
<h4>price: {item.price}</h4>
</div>
))}
</div>
<div
className="main-title"
style={{
textAlign: "center",
justifyContent: "center",
alignItems: "center",
fontSize: 14,
}}
>
<h1>Bakery</h1>
<h1>Company Gbr</h1>
<h1>Oranienburger Straße 120</h1>
<h1>10119 Berlin</h1>
</div>
<div className="bills-container">
<div></div>
{/* pass in the details */}
<div className="item-list">
{items &&
items.items &&
items.items.map((item) => (
<React.Fragment key={item.id}>
<div className="bill-time">
<div className="bill">
<h4>
{" "}
<strong>Bill: </strong>
{item.billNumber}
</h4>
</div>
<div className="time">
<h4>
{" "}
<strong>Time: </strong>
{item.created_datetime}
</h4>
</div>
</div>
----------------------------------
----------------------------------
---------------------------------- --------------------
{/* Counter */}
<div className="price-total">
<div className="title">
<h3>
{" "}
<strong>Title: </strong>
{item.title}
</h3>
<div className="counter">
<strong>
<Display message={counter} />x
</strong>
</div>
</div>
<div className="increase">
<button onClick={() => setCounter(counter + 1)}>+</button>
</div>
<div className="decrease">
<button onClick={() => setCounter(counter - 1)}>-</button>
</div>
{/* Price and total */}
<div className="price">
<h4>
<strong>Price: {parseFloat(item.price)}€</strong>
</h4>
</div>
<div className="total">
<h4>Total: {parseFloat(item.price * counter)}€</h4>
</div>
</div>
</React.Fragment>
))}
</div>
{/* <div>
<h4>
Table: Counter
Terminal:
Ust-Id: DE11111111</h4>
</div> */}
</div>
<div className="button-path">
<Link to="/items">
<div className="button">
<button className="main-button">Analyse Receipt</button>
</div>
</Link>
</div>
<Switch>
<Route path="/bills/:id" />
</Switch>
</div>
);
}
const mapStateToProps = (state) => {
return {
items: state.items,
};
};
const mapDispatchToProps = (dispatch) => {
return {
getItems: () => dispatch(getItems()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(BillList);
The ":" of path="/bills/:id" is only used to designate id as a route parameter, it isn't meant to be part of any URL. When you link to to={`/bills/:${items.id}`} you are adding ":" to the id string value.
Remove it from the link. You should also ensure that the Items component has items to map, where each specific item mapped renders the link/button to link to the appropriate bill list page.
<Link to={`/bills/${item.id}`}>
<button className="button4">Analyse Receipt</button>
</Link>
The Items route also doesn't specify any route params, so there will be be none in the `Items component.
<Route exact path="/" component={Items} />
I am working on a react project with similar functionality to a social media site. I have a user profile component below that has links to other user profiles(towards bottom of code below) that are being followed by the current user. Essentially what I am trying to do is re-render the same component with a different user. However, the link to the new user profile doesn't result in the getProfile action getting called so the redux state doesn't update. How can I navigate to the new profile and have the useEffect hook get called again with the new username?
Thank You!
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import GalleryItem from "../gallery-item/gallery-item.component";
import {
getProfile,
addFollow,
removeFollow
} from "../../redux/profile/profile.actions";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faSpinner, faUserEdit } from "#fortawesome/free-solid-svg-icons";
const Profile = ({
getProfile,
addFollow,
removeFollow,
auth,
profile: { userProfile, loading },
props
}) => {
const userAlias = props.match.params.alias;
useEffect(() => {
getProfile(userAlias);
}, [getProfile]);
return loading ? (
<div class="d-flex justify-content-center">
<FontAwesomeIcon
icon={faSpinner}
className="fa-spin"
style={{ height: "50px", width: "50px", color: "white" }}
/>
</div>
) : (
<div className="container ">
<div className="row">
<div className="col-md-12 align-self-center">
<img
className="rounded-circle float-left shadow-lg"
alt="100x100"
src={userProfile.userProfileImage}
data-holder-rendered="true"
style={{ height: "200px", width: "200px" }}
/>
<div
className="vertical-center"
style={{ marginLeft: "260px", marginTop: "50px" }}
>
<h2>
{auth.user === null || auth.user.alias !== userAlias ? (
<b style={{ color: "white" }}>{userAlias}</b>
) : auth.user.alias === userAlias ? (
<b style={{ color: "white" }}>
{userAlias}
<Link className="" to="/profile/edit">
<FontAwesomeIcon
icon={faUserEdit}
className="fontAwesome"
style={{ paddingLeft: "10px", color: "limegreen" }}
/>
</Link>
</b>
) : (
<b>{userAlias}</b>
)}
</h2>
<p>
<b style={{ color: "white" }}>
{" "}
{userProfile.posts.length} Posts
</b>
<b style={{ color: "white" }}>
{" "}
{userProfile.followers.length} Followers{" "}
</b>
<b style={{ color: "white" }}>
{" "}
{userProfile.following.length} Following{" "}
</b>
</p>
{auth.user === null || auth.user.alias === userAlias ? null : auth
.user.alias !== userAlias &&
userProfile.followers.some(
e => e.userAlias === auth.user.alias
) ? (
<button
type="button"
className="btn btn-primary btn-lg "
onClick={e => removeFollow(userProfile.userId)}
>
Following
</button>
) : auth.user.alias !== userAlias ? (
<button
type="button"
className="btn btn-primary btn-lg "
onClick={e => addFollow(userProfile.userId)}
>
Not Following
</button>
) : (
<button
type="button"
className="btn btn-primary btn-lg "
disabled
>
Follow/Unfollow
</button>
)}
</div>
</div>
</div>
<hr />
<div className="row d-flex justify-content-center">
{userProfile.posts.map((post, i) => (
<GalleryItem key={i} post={post} />
))}
</div>
{userProfile.following.length > 0 ? (
<div>
<h1 className="text-white text-center mt-5">Following</h1>
<hr />
**<div className="row justify-content-center text-center px-auto">
{userProfile.following.map((profile, i) => (
<Link className="" to={`/profile/${profile.userAlias}`}>
<img
className="rounded-circle border border-info m-4"
alt="100x100"
src={profile.getFollowingUserProfileImageUrl}
data-holder-rendered="true"
style={{ height: "80px", width: "80px" }}
/>
<div
className="vertical-center"
style={{ marginBottom: "20px", color: "black" }}
>
<h5>{profile.userAlias}</h5>
</div>
</Link>
))}
</div>**
</div>
) :(<div></div>)}
</div>
);
};
Profile.propTypes = {
getProfile: PropTypes.func.isRequired,
profile: PropTypes.object.isRequired,
auth: PropTypes.object.isRequired,
props: PropTypes.object.isRequired
};
const mapStateToProps = (state, ownProps) => ({
auth: state.auth,
profile: state.profile,
props: ownProps
});
export default connect(
mapStateToProps,
{ getProfile, addFollow, removeFollow }
)(Profile);
You need to track userAlias in the useEffect's dependencies list, the api callback will be called each time it changes.
const userAlias = props.match.params.alias;
useEffect(() => {
getProfile(userAlias);
}, [getProfile, userAlias]);
I have a footer that I created in App.js and now I have another component called KokPlayer.js and I want to add buttons from KokPlayer.js to the footer in App.js.
How can I do that?
App.js
render() {
const { expanded } = this.state;
return (
<React.Fragment>
<nav
className="footer navbar navbar-light bg-success mb-auto"
ref="footerRef"
/>
</React.Fragment>
);
}
KokPlayer.js
render() {
// Add this block to footer
return (
<div
style={{ display: "block", margin: "0 auto", verticalAlign: "middle" }}
>
<Button onClick={this.play} className="mr-3">
play()
</Button>
<Button onClick={this.pause} className="mr-3">
pause()
</Button>
<Button onClick={this.toggleFullScreen} className="mr-3">
FullScreen()
</Button>
</div>
);
}
As I understand what you wrote in the comments, you can pass a prop to KokPlayer component then you can hide the elements that you don't want to show them up in App.js
in App.js
import KokPlayer from './KokPlayer' // KokPlayer location
....
render() {
const { expanded } = this.state;
return (
<React.Fragment>
<nav
className="footer navbar navbar-light bg-success mb-auto"
ref="footerRef"
/>
<KokPlayer showButtonsOnly={true} /> // the buttons here
</React.Fragment>
);
}
KokPlayer.js
render() {
// Add this block to footer
return (
<div>
{!this.props.showButtonsOnly && <div> // it wouldn't be shown in App.js
Screen Here
</div>}
<div style={{ display: "block", margin: "0 auto", verticalAlign: "middle" }}
>
<Button onClick={this.play} className="mr-3">
play()
</Button>
<Button onClick={this.pause} className="mr-3">
pause()
</Button>
<Button onClick={this.toggleFullScreen} className="mr-3">
FullScreen()
</Button>
</div>
</div>
);
}