Some div are created automatically in react - reactjs

I have a react code like below
<div className="grid-container">
<header>
<Header />
</header>
<main>
{(userInfo?.isAdmin === false || !userInfo) &&
location.pathname === '/' && <Carousel />}
<div className={userInfo?.isAdmin ? 'row stretch left' : 'row'}>
{userInfo?.isAdmin && <Sidebar listItems={listItems} />}
<Content />
</div>
</main>
<footer className="row center">All rights reserved.</footer>
</div>
Output
In that screenshot, some div are created automatically. In component , There is no such a div in between sidebar class and row class. But I don't Know how it comes. Please help me..
Sidebar component:
export default function Sidebar(props) {
const items = props.listItems;
const location = useLocation();
return (
<ul className="sidebar">
{items.map((list) => (
<li key={list.link} className={`sidebar__item`}>
<Link
to={`/${list.link}`}
className={`sidebar__link ${
location.pathname === '/' && list.link === 'dashboard'
? 'active__link'
: location.pathname === '/' + list.link
? 'active__link'
: ''
}`}
>
{list.name === 'Dashboard' ? (
<ColumnsGap className="sidebar__icon" />
) : list.name === 'Products' ? (
<BoxSeam className="sidebar__icon" />
) : list.name === 'Orders' ? (
<BagCheck className="sidebar__icon" />
) : list.name === 'UsersList' ? (
<People className="sidebar__icon" />
) : (
''
)}
{list.name}
</Link>
</li>
))}
</ul>
);
}
Content Component:
export default function Content() {
const userSignin = useSelector((state) => state.userSignin);
const { userInfo } = userSignin;
return (
<>
<Route path="/product/:id" exact component={ProductScreen}></Route>
<Route path="/cart/:id?" exact component={CartScreen}></Route>
</>
);
}
ProductScreen:
export default function ProductScreen(props) {
return (
<>
{loading ? (
<LoadingBox></LoadingBox>
) : error ? (
<MessageBox>{error}</MessageBox>
) : (
<div className="">
<div className="row">
<div className="col-3">
<div className="col-1">Image</div>
<div className="col-1">Image Details</div>
</div>
<div className="col-1">
</div>
</div>
</div>)
}
Cart Component:
export default function CartScreen(props) {
return (
<div>
<h1 className="mb-1">Shopping Cart</h1>
<div className="row top">
<div className="col-2">
</div>
</div>
</div>)
}
Like above all components are enclosed with div tag or empty tag.But there are more empty div tag are produced automatically.

Related

How can I use ref for another component?

So I have a sidebar with list of items, and when I click on an item, it should scroll to a certain div, which are outside components. Sidebar looks like this:
Sidebar component:
const Sidebar = () => {
const [sideBar, setSidebar] = useState(false);
return (
<div className="sidebar">
<span class="btn" onClick={() => setSidebar(!sideBar)}>Menu</span>
<div className="profile">
<img src={spike}/>
<span>Alim Budaev</span>
<span>Available for work</span>
</div>
<ul className="sidebarlist" id={sideBar ? "hidden" : ""}>
{SlidebarData.map((val,key) =>{
return (
<li
className="row"
id={window.location.pathname === val.link ? "active" : ""}
key={key}
onClick={()=> {
}}>
{""}
<div>
{val.title}
</div>
</li>
);
})}
</ul>
</div>
);
}
Components in App.js:
function App() {
return (
<div className="App">
<div className="header">
<Sidebar/>
<Hero">
<Particles/>
</Hero>
<About/>
<Service/>
<Form/>
<Footer/>
</div>
</div>
);
}
So I'm looking to way to scroll to a certain component when I click on . I know it can be made through useRef(), but I don't know how to do it in the Sidebar with outside components.

How can you update the props of a single element of an array using state?

I'm trying to create a component that allows a video to autoplay on mouseenter and pauses on mouseleave. However, the current code causes all videos to autoplay when you put the mouseover any single one of the videos. How can I only make the video that you're interacting with update its state in a more isolated way?
I can't seem to find a solution using React hooks anywhere, that I can understand and implement into my own code.
export default function VideoGrid(props) {
const [playing, setPlaying] = useState(false);
return (
<div>
<div className={styles.VideoGrid}>
<div className="container">
<h2 className={styles.title + " text-lg uppercase title"}>{props.title}</h2>
<div className={styles.videos}>
{props.videos ? videos.output.map((video, index) => {
return (
<div className={styles.video} key={index}>
{ video.acf.video_url ? (
<ReactPlayer
controls={false}
playing={playing}
onMouseEnter={() => setPlaying(true)}
onMouseLeave={() => setPlaying(false)}
height={205}
url={video.acf.video_url + '&showinfo=0&controls=0&autohide=1'}
width='100%'
config= {{
youtube: {
playerVars: {showinfo: 0, controls: 0}
}
}}
/>
) : (
<img src={video._embedded ? video._embedded['wp:featuredmedia'][0].media_details.sizes.full.source_url : '/logo.svg'} height={205} />
)}
<p className="mt-2">{video.title.rendered}</p>
{video.acf.description && router.pathname != '/' ? <p className={styles.description + " text-xs"}>{video.acf.description}</p> : ''}
</div>
)
}) : ''}
</div>
</div>
</div>
</div>
)
}
You can create a separate component and deal with the state individually.
const Video = (props) => {
const [playing, setPlaying] = useState(false);
return (
<div className={styles.video} key={index}>
{video.acf.video_url ? (
<ReactPlayer
controls={false}
playing={playing}
onMouseEnter={() => setPlaying(true)}
onMouseLeave={() => setPlaying(false)}
height={205}
url={video.acf.video_url + "&showinfo=0&controls=0&autohide=1"}
width="100%"
config={{
youtube: {
playerVars: { showinfo: 0, controls: 0 },
},
}}
/>
) : (
<img
src={
video._embedded
? video._embedded["wp:featuredmedia"][0].media_details.sizes.full
.source_url
: "/logo.svg"
}
height={205}
/>
)}
<p className="mt-2">{video.title.rendered}</p>
{video.acf.description && router.pathname != "/" ? (
<p className={styles.description + " text-xs"}>
{video.acf.description}
</p>
) : (
""
)}
</div>
);
};
export default Video;
Then render it in your map. You need to do the proper changes to pass your data into the video component.
export default function VideoGrid(props) {
return (
<div>
<div className={styles.VideoGrid}>
<div className="container">
<h2 className={styles.title + " text-lg uppercase title"}>
{props.title}
</h2>
<div className={styles.videos}>
{props.videos
? videos.output.map((video, index) => {
return <Video />;
})
: ""}
</div>
</div>
</div>
</div>
);
}

Remove previous content when new one is rendered through a condition (React)

I have a navbar that uses eventKeys to switch between the buttons
const CustomNav = ({ active, onSelect, ...props }) => {
return (
<Nav
{...props}
activeKey={active}
onSelect={onSelect}
style={{ marginBottom: "15px" }}>
<Nav.Item eventKey='all'>All</Nav.Item>
<Nav.Item eventKey='movies'>Movies</Nav.Item>
<Nav.Item eventKey='shows'>Shows</Nav.Item>
<Nav.Item eventKey='people'>People</Nav.Item>
</Nav>
);
};
I did this:
const Content = () => {
if (this.state.active === "all") {
return (
<div>
{trending.results &&
trending.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
} else if (this.state.active === "movies") {
return (
<div>
{trendingMovies.results &&
trendingMovies.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
}
};
Called it here:
return (
<div className='Home'>
<FlexboxGrid justify='center'>
<Panel bordered header='Trending today!'>
<CustomNav
className='customNav'
appearance='subtle'
active={active}
onSelect={this.handleType}
/>
<Content />
<Pagination
{...this.state}
style={{ marginTop: "15px" }}
maxButtons={5}
size='sm'
pages={totalPages}
activePage={this.state.activePage}
onSelect={this.handlePage}
/>
</Panel>
</FlexboxGrid>
</div>
);
}
}
To display the correct data for each tab, but when I'm on the movies tab it shows all the data from the first "all" tab + data on the "movies" tab. I wanna show each data individually corresponding to the correct tab which is controlled by "this.state.active". Tried a switch statement too and that did not work
you are using the arrow syntax
const Content = () => { ... }
and also using this.state variable in your code !!!
if you want to use this.state, then you want to use the class syntax, like
class Content extends React.Component { ... }
but don't mix the two styles.
what you are probably wanting to do is to send the active variable as a prop
try:
const Content = ({active}) => {
if (active === 'all') {
return (...)
} else if (active === 'movies') {
return (...)
}
return null
}
and where you are calling the component you send the active value in as a prop
<Content active={active} />
Note also that you are using the variables trending and trendingMovies and it is unclear where those come from, you may need to send those via props also.
Now you can also leave the if..else logic outside of your Content component like so
const Content = ({myTrending}) => {
return (
<div>
{myTrending.results &&
myTrending.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
}
and then where you call that component you have
<Content
myTrending={active === 'all' ? trending : trendingMovies}
/>
You need to pass active and other variables as props to the Content component, since it doesn't access them otherwise:
const Content = ({active, trending=[], trendingMovies=[]}) => {
if (active === "all") {
return (
<div>
{trending.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
} else if (active === "movies") {
return (
<div>
{trendingMovies.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
}
};
return (
<div className='Home'>
<FlexboxGrid justify='center'>
<Panel bordered header='Trending today!'>
<CustomNav
className='customNav'
appearance='subtle'
active={active}
onSelect={this.handleType}
/>
<Content active={this.state.active} trending={this.state.trending} trendingMovies={this.state.trendingMovies} />
<Pagination
{...this.state}
style={{ marginTop: "15px" }}
maxButtons={5}
size='sm'
pages={totalPages}
activePage={this.state.activePage}
onSelect={this.handlePage}
/>
</Panel>
</FlexboxGrid>
</div>
);
}
}

Cart value resets on browser refresh

In ECommerce React project, I've created cart when clicked, changes to 'In Cart' and is then disabled which shows the product is in cart and can't be clicked back, but, when browser is refreshed Cart value resets back.
Following is the code reference
Product.js
export default class Product extends Component {
render() {
const {id, title, img, price, inCart} = this.props.product;
const dataValue = JSON.parse(localStorage.getItem('myCart'))
return (
<ProductWrapper className="col-9 mx-auto col-sm-6 col-lg-3 my-3 " >
<div className="card" >
<ProductConsumer>
{(value) => (
<div className="img-container p-3" >
<img style={imageSize} src={img} alt="product"
className="card-img-top center img-fluid img-responsive"/>
<button className="cart-btn" disabled={inCart?true:false}
onClick={() => {value.addToCart(id)}}>
{console.log('DATA VALUE', dataValue)}
{ inCart ? (
<p className="text-capitalize mb-0" disabled>
{" "}
In Cart</p>
) : (
<i className="fas fa-shopping-cart"/>
)}
</button>
</div>)}
</ProductConsumer>
</div>
</ProductWrapper>
);
}
}
ProductList.js (Mapping list of products)
export default class ProductList extends Component {
render() {
return (
<React.Fragment>
<ProductConsumer>
{value => {
return value.products.map((product, key) => {
return <Product key={product.id} product={product} />;
});
}}
</ProductConsumer>
</React.Fragment>
);
}
}
App.js
class App extends Component {
render() {
return (
<React.Fragment>
<Route render={({location}) => (
<Switch location={location}>
<Route exact path="/" component={ProductList}/>
</Switch>
)} />
</React.Fragment>
);
}
}
export default App;
I've tried with localStorage but no effect. What can be done to make the cart value store in localStorage, so that when refreshed 'In Cart' remains. Any appropriate solution?
Following is the codesandbox link: https://codesandbox.io/s/tdgwm
<button
className="cart-btn"
disabled={inCart ? true : false}
onClick={() => {
value.addToCart(id);
localStorage.setItem("added", "In Cart");
console.log(localStorage.getItem("added"));
}}
>
{localStorage === null ? (
<i className="fas fa-shopping-cart" />
) : (
<p className="text-capitalize mb-0" disabled>
{" "}
{localStorage.getItem("added")}
</p>
)}
</button>
I took a quick look at this. The above code will get the localStorage item set and render the in cart value. However, I will leave it to you to apply it to the individual product and update the conditionality for the icon/in cart piece. I'll be on for a little bit longer if you have any questions. But basically you need to see if localstorage is set prior to rendering.
It is because you don't check the local storage inCart value in the Product.js
I have added another condition like below and check it within inCart in the conditions
...
...
const localInCart = dataValue
&& dataValue.find(i => i.id === id)
&& dataValue.find(i => i.id === id).inCart;
...
...
...
(inCart || localInCart) ? ...)
you can see the result on codesandbox; https://codesandbox.io/s/mobile-store-ufxgp?fontsize=14&hidenavigation=1&theme=dark

Conditional Rendering of div in ReactJS?

I'm a newbie to ReactJS. I want to insert a condition in my code below so that when noPeopleText.length > 0, then only should the "no-people-row" div render, otherwise, I do not want this div rendering to the DOM if noPeopleText is an empty string or undefined.
What's the best way do add in a conditional for this?
const peopleMember = (props) => {
const { people, noPeopleText, title } = props;
const hasPeople = Boolean(people && people.length);
const peopleGroup = _.groupBy(people, (person, i) =>
Math.floor(i / 2)
);
return (
<div>
{ hasPeople &&
<SectionHeader
title={title}
/>
}
{ (hasPeople || noPeopleText) &&
<div className="c-team-members">
<div className="container">
{ hasPeople ? _.map(peopleMemberGroups, (members, i) => (
<div className="row" key={i}>
{members && members.map((member, j) => (
<TeamMember
key={j}
name={member.name}
/>
))
}
</div>
)) : //If noPeopleText.length > 0, render div below
<div className="row no-people-row">
<div className="col-xs-12" dangerouslySetInnerHTML={{__html: noPeopleText}} />
</div>
}
</div>
</div>
}
</div>
);
};
You already have conditional rendering in your code. For example:
{ hasPeople &&
<SectionHeader title={title} />
}
This will only render the component SectionHeader if hasPeople evaluates to true. If hasPeople evaluates to false then the whole expression would evaluate to false regardless of the second part of the &&. Thus it is never executed (rendered).
So do you want something like this?
const peopleMember = (props) => {
const { people, noPeopleText, title } = props;
const hasPeople = Boolean(people && people.length);
const peopleGroup = _.groupBy(people, (person, i) =>
Math.floor(i / 2)
);
return (
<div>
{ hasPeople &&
<SectionHeader
title={title}
/>
}
{ (hasPeople || noPeopleText) &&
<div className="c-team-members">
<div className="container">
{ hasPeople ? _.map(peopleMemberGroups, (members, i) => (
<div className="row" key={i}>
{members && members.map((member, j) => (
<TeamMember
key={j}
name={member.name}
/>
))
}
</div>
)) : (noPeopleText.length > 0) &&
<div className="row no-people-row">
<div className="col-xs-12" dangerouslySetInnerHTML={{__html: noPeopleText}} />
</div>
}
</div>
</div>
}
</div>
);
};
I think you can just use a nested ternary operator:
{ hasPeople
? //mapping
: noPeopleText.length > 0
? <div className="row no-people-row">
<div className="col-xs-12" dangerouslySetInnerHTML={{__html: noPeopleText}} />
</div>
: null
}

Resources