One of my current projects is learning React and coding in general by analyzing and playing with specific code fragments.
But now I'm stuck. I think I know what the problem is, but I can't solve it.
I have 2 tabs. Tab 1 is set as active, so it's content is shown if i vist the site. Tab 2 is set as inactive. If I click on Tab 2, the state is simply switched. This works.
But if I add a third tab as in this example, the behaviour get's weird.
If I click on Tab 2, Tab 3 is set as active as well and both contents are shown.
I would really appreciate some help. I don't want to give up understanding this.
Thanks!
const [main__tab_state, set_main__tab_state] = useState(true);
<div className="main__tab">
<div className="page__flex">
<div className="main__tab--box">
<div className="main__tab--head">
<ul>
<li className={main__tab_state ? "active" : ""}>
<a className="js-tab" data-tab="tab" onClick={() => set_main__tab_state(true)}>TAB NAME 1</a>
</li>
<li className={main__tab_state ? "" : "active"}>
<a className="js-tab" data-tab="tab1" onClick={() => set_main__tab_state(false)}>TAB NAME 2</a>
</li>
<li className={main__tab_state ? "" : "active"}>
<a className="js-tab" data-tab="tab2" onClick={() => set_main__tab_state(false)}>TAB NAME 3</a>
</li>
</ul>
</div>
</div>
<div className="main__tab--box">
<div className="main__tab--body js-tab__body">
<div id="tab" className={`main__tab--item${main__tab_state ? "active" : ""}`}>
<div className="text">
<p>
TAB TEXT 1
</p>
</div>
</div>
<div id="tab1" className={`main__tab--item${main__tab_state ? "" : "active"}`}>
<div className="text">
<p>
TAB TEXT 2
</p>
</div>
</div>
<div id="tab2" className={`main__tab--item${main__tab_state ? "" : "active"}`}>
<div className="text">
<p>
TAB TEXT 3
</p>
</div>
</div>
</div>
</div>
</div>
</div>
Use const [activeTabIndex, setActiveTabIndex] = useState(0); instead.
Then just kodify your code like so:
<a className="js-tab" data-tab="tab" onClick={() => setActiveTabIndex(0)}>TAB NAME 1</a>
<div id="tab" className={`main__tab--item${activeTabIndex === 0 ? "active" : ""}`}>
First of all you need to change your state.
const [main__tab_state, set_main__tab_state] = useState("tab1"); // change state to store string values and default we will store tab1
Change your code to render tabs and content like below:-
<div className="main__tab">
<div className="page__flex">
<div className="main__tab--box">
<div className="main__tab--head">
<ul>
<li className={main__tab_state === "tab1" ? "active" : ""}>
<a className="js-tab" data-tab="tab" onClick={() => set_main__tab_state("tab1")}>TAB NAME 1</a>
</li>
<li className={main__tab_state === "tab2" ? "" : "active"}>
<a className="js-tab" data-tab="tab1" onClick={() => set_main__tab_state("tab2")}>TAB NAME 2</a>
</li>
<li className={main__tab_state === "tab3" ? "" : "active"}>
<a className="js-tab" data-tab="tab2" onClick={() => set_main__tab_state("tab3")}>TAB NAME 3</a>
</li>
</ul>
</div>
</div>
<div className="main__tab--box">
<div className="main__tab--body js-tab__body">
<div id="tab" className={`main__tab--item${main__tab_state === "tab1" ? "active" : ""}`}>
<div className="text">
<p>
TAB TEXT 1
</p>
</div>
</div>
<div id="tab1" className={`main__tab--item${main__tab_state === "tab2" ? "" : "active"}`}>
<div className="text">
<p>
TAB TEXT 2
</p>
</div>
</div>
<div id="tab2" className={`main__tab--item${main__tab_state === "tab3" ? "" : "active"}`}>
<div className="text">
<p>
TAB TEXT 3
</p>
</div>
</div>
</div>
</div>
</div>
</div>
Related
I have a react.js useState that I set to false by default. So, what I want to do is to change it to true when an edit button is clicked. It is actually array of comments that I mapped and displayed individually. I would like the user to be able to edit the comment he or she made and clicked the edit button specifically for that comment. Here are my codes:
const [updateComment, setUpdateComment] = useState(false)
<h5 className='users-comment'>Users comments</h5>
{comments.map((singleComment, _id)=>{
return(
<>
{updateComment ?
<div className='comment-div' key={_id}>
<textarea className='comment-wrapper' type='text' placeholder='Share your comment'
onChange={(e) => setCommentDescription(e.target.value)}
></textarea>
<button className='comment-btn'onClick={handleCommentUpdate}>Update Post</button>
</div>
:
<div className='displayed-comments'>
<div className="commentPic">
<img className="user-pics" src={PF + singleComment.author.profilePicture} alt="" />
</div>
<div className="comment-info">
<div className="comment-author-div">
<div className='comment-author-date-info'>
<h4 className="comment-author">{singleComment.author.username}</h4>
<p className="comment-date">{new Date(singleComment.createdAt).toDateString()}
</p>
</div>
<div className="comment-edit-delete-div">
<i className="singlePostIcon fas fa-edit" onClick={() => setUpdateComment(true)} ></i>
<i className="singlePostIcon far fa-trash-alt" ></i>
</div>
</div>
<p className="comment-content">{singleComment.commentdescription}</p>
</div>
</div>
}
</>
)
})}
The edit button is this line of code:
<i className="singlePostIcon fas fa-edit" onClick={() => setUpdateComment(true)} ></i>
But with this current line of codes, once I click on that edit button, it affects all the comments that are on display. I just want it to affect only the comment that I clicked on, so that I can edit that particular comment. Thank you as you.
You need to put the state in a single Comment component, so every component have a specific state.
OR you can set the _id of the edited comment in the state. like this:
<i
className="singlePostIcon fas fa-edit"
onClick={() => setUpdateComment(_id)} // <===
/>
and instead of
{updateComment ?
<div className='comment-div' key={_id}>
...
do it like that:
{updateComment === _id ?
<div className='comment-div' key={_id}>
...
I have data that I am looping through and I have a slight issue with a dropdown menu. Whenever I click the dropdown button for a single post all the other posts open. And I don't know to solve it.
Here is the React code
const Post = () {
const [open, setOpen] = useState(false)
return(
{posts.map((post) => {
return (
<div className="card" key={post.postId}>
<div className="card-header">
<div className="card-header__avatar">
<img
src="https://source.unsplash.com/user/erondu/40x40"
alt=""
/>
</div>
<div className="card-header__username">
<span>
<strong>
{post.firstname} {post.lastname}
</strong>
</span>
<br />
<span>
<small>{date}</small>
</span>
</div>
<div
className="card-header__moreBtn"
onClick={() => setOpen(!open)}
>
<img src={More} alt="" />
{open && ( ------> here is where the problem comes
<div class="dropdown-wrapper">
<ul class="dropdown-menu">
<li class="dropdown-menu__item">
<Link href="#d" onClick={deletePost}>Edit</Link>
</li>
<li class="dropdown-menu__item">
<Link className="dropdown-menu__item__link" onClick={deletePost}>Delete</Link>
</li>
</ul>
</div>
)}
</div>
</div>
<div className="postDescription">
<p>{post.postDescription}</p>
</div>
<div className="imgPost">
<img src={post.image} alt="" />
</div>
</div>
)
})}
)
}
Here is a picture
Any help will suffice and I appreciate your time.
You're using the same state value for all items in your loop, so naturally they are going to all follow the same directive.
I would recommend creating a PostItem component that maintains its own state. Something like this:
const PostItem = ({post}) => {
const [open, setOpen] = useState(false)
return (
<div className="card" key={post.postId}>
<div className="card-header">
<div className="card-header__avatar">
<img
src="https://source.unsplash.com/user/erondu/40x40"
alt=""
/>
</div>
<div className="card-header__username">
<span>
<strong>
{post.firstname} {post.lastname}
</strong>
</span>
<br />
<span>
<small>{date}</small>
</span>
</div>
<div
className="card-header__moreBtn"
onClick={() => setOpen(!open)}
>
<img src={More} alt="" />
{open && (
<div class="dropdown-wrapper">
<ul class="dropdown-menu">
<li class="dropdown-menu__item">
<Link href="#d" onClick={deletePost}>Edit</Link>
</li>
<li class="dropdown-menu__item">
<Link className="dropdown-menu__item__link" onClick={deletePost}>Delete</Link>
</li>
</ul>
</div>
)}
</div>
</div>
<div className="postDescription">
<p>{post.postDescription}</p>
</div>
<div className="imgPost">
<img src={post.image} alt="" />
</div>
</div>
)
})
}
const AllPosts = ({posts}) {
return(
{posts.map(post => <PostItem post={post} />
)
}
Now each PostItem has a separate, internal instance of open in its own state and will act independently from the others.
I have passed the data via props, the console logs show me the data being passed. here is the code below
import React, { Component } from 'react';
import "../../../node_modules/bootstrap/dist/css/bootstrap.min.css";
import "./TestimonialCard.css";
const Cards = ({cardData}) =>{
console.log(cardData);
return(
<>
<div className="container">
<div className="row">
<div className="col-md-8 col-center m-auto">
<h2>Testimonials</h2>
<div id="myCarousel" className="carousel slide" data-ride="carousel" >
<div className="carousel-inner">
{cardData.map((slide , index )=>{
{console.log(slide)}
<div className="item carousel-item active" key={index} >
<div className="img-box">
<img src={slide.image} alt={slide.alt}/>
</div>
<p className="testimonial">
{slide.testimonial}
</p>
<p className="overview">
<b> {slide.name} </b> ,<span>{slide.designation}</span>
</p>
</div>
})}
</div>
<a className="carousel-control left carousel-control-prev" href="myCarousel" data-slide="prev">
<i className="fa fa-angle-left"></i>
</a>
<a className="carousel-control right carousel-control-next" href="myCarousel" data-slide="next">
<i className="fa fa-angle-right"></i>
</a>
</div>
</div>
</div>
</div>
</>
)
}
export default Cards
Here, I'm not getting an expected UI under my div with carousel-inner class.
You can use it like this:
import React, { Component } from 'react';
import "../../../node_modules/bootstrap/dist/css/bootstrap.min.css";
import "./TestimonialCard.css";
const Cards = ({cardData}) =>{
console.log(cardData);
const cardData = (cardData) => {
cardData.map((slide, index) => {
return (
<div className="item carousel-item active" key={index}>
<div className="img-box">
<img src={slide.image} alt={slide.alt}/>
</div>
<p className="testimonial">
{slide.testimonial}
</p>
<p className="overview">
<b> {slide.name} </b> ,<span>{slide.designation}</span>
</p>
</div>
)
})
}
return(
<>
<div className="container">
<div className="row">
<div className="col-md-8 col-center m-auto">
<h2>Testimonials</h2>
<div id="myCarousel" className="carousel slide" data-ride="carousel" >
<div className="carousel-inner">
{cardData()}
</div>
<a className="carousel-control left carousel-control-prev" href="myCarousel" data-slide="prev">
<i className="fa fa-angle-left"></i>
</a>
<a className="carousel-control right carousel-control-next" href="myCarousel" data-slide="next">
<i className="fa fa-angle-right"></i>
</a>
</div>
</div>
</div>
</div>
</>
)
}
export default Cards
The reason UI was not rendering is because you are using {} instead of () in map inside JSX.
If you want to use map inside render() or the JSX you need to use () instead of {} like this:
{cardData.map((slide , index )=> (
{console.log(slide)}
<div className="item carousel-item active" key={index} >
<div className="img-box">
<img src={slide.image} alt={slide.alt}/>
</div>
<p className="testimonial">
{slide.testimonial}
</p>
<p className="overview">
<b> {slide.name} </b> ,<span>{slide.designation}</span>
</p>
</div>
))}
I am having an ecommerce application build in next.js. In this I have top bar contains contact and other link information, below that there is a long and search section. This two items are done in 2 components and both are combined.
Now the problem is, on hover any link in components, the particular page in refreshed (not reloading). What may be the problem. For better understanding I have placed a video blow. Please check.
https://www.dropbox.com/s/tlh4e2os1ok2tpr/screen-recording.webm?dl=0
I have given all link as below,
<Link href="/" as="/">
<a className="mr-4">Help Center</a>
</Link>
Please check my below codes,
Top.js
const Top = () => {
return (
<div>
<div className="topBar">
<div className="container">
<div className="row">
<div className="col-sm-4 col-md-6">
<p className="text-center text-sm-left">
<Link href="/" as="/">
<a>Sell in RangerBee</a>
</Link>
</p>
</div>
<div className="col-sm-8 col-md-6">
<p className="text-center text-sm-right">
<Link href="/" as="/">
<a className="mr-4">Gift Card</a>
</Link>
<Link href="/" as="/">
<a className="mr-4">Help Center</a>
</Link>
<Link href="/" as="/">
<a>Download app</a>
</Link>
</p>
</div>
</div>
</div>
</div>
</div>
}
export default Top;
Header.js
const Header = () => {
return (
<div>
<div className="searchBar">
<div className="container-fluid">
<div className="row align-items-center">
<div className="col-8 col-md-2 col-lg-2">
<p>
<Link href="/" as="/">
<a><img src="/vercel.svg" alt="Example" className="img-fluid" /></a>
</Link>
</p>
</div>
<div className="col-4 col-md-2 col-lg-3 col-xl-2">
<div className="menuCategory">
<p className="main" onClick={() => changeMenuCategory()}><span>Shop By Category</span> <FontAwesomeIcon icon={faChevronDown} className="ml-2 pt-1 fa-down"/> <FontAwesomeIcon icon={faBars} className="ml-2 pt-1 fa-bars"/></p>
<ul className={toggleCategory ? "main-nav" : "main-nav d-none"}>
{menus && menus.data.map((cat, index) => (
<li key={index}>
<Link href={"/products/"+cat.cat_slug} as={"/products/"+cat.cat_slug}><a title={cat.cat_name}>{cat.cat_name} <FontAwesomeIcon icon={faChevronRight} className="ml-2 float-right menu-arrow"/></a></Link>
<ul>
{cat.subcategory.map((subcat, index1) => (
<li key={index1+index}><Link href={"/products/"+cat.cat_slug+"/"+subcat.sub_slug} as={"/products/"+cat.cat_slug+"/"+subcat.sub_slug}><a title={subcat.sub_name}>{subcat.sub_name}</a></Link></li>
))}
</ul>
</li>
))}
</ul>
</div>
</div>
<div className="col-12 col-md-4 col-lg-4 col-xl-5 mt-3 mb-3 mt-md-0 mb-md-0">
<div className="search-box">
<div className="search-inner">
<input type="text" name="q" placeholder="Search for products, brands and much more" onClick={() => setToggleSearch(b => !b)} onFocus={(e) => trendingSearch(e)} onChange={(e) => startSearch(e)} />
<button><FontAwesomeIcon icon={faSearch}/></button>
</div>
<div className={toggleSearch ? "search-result" : "search-result d-none"}>
<ul ref={dropdown}>
{trending !== null && searched === null && trending.data.length > 0 && <li className="trending">Trending Search</li>}
{trending !== null && searched == null && trending.data.length > 0 &&
trending.data.map((trending, index) => (
<li key={index}><Link href={"/products/"+trending.trending_slug} as={"/products/"+trending.trending_slug}><a>{trending.trending_name}</a></Link></li>
))
}
{searched !== null && searched.data.length > 0 &&
searched.data.map((search, index) => (
<li key={index}>
<Link href={search.search_url} as={search.search_url}>
{search.images.length > 0 ?
<a><img src={api.IMAGE_PRODUCTS+"/"+search.images[0].image_name} alt={search.search_name} /> {search.search_name}</a>
:
<a>{search.search_name}</a>
}
</Link>
</li>
))
}
</ul>
</div>
</div>
</div>
<div className="col-12 col-md-4 col-lg-3">
<div className="text-center text-md-right">
<div className="d-inline loginDrop">
<Link href={!isAuthenticated ? "/login" : "/profile"} as={!isAuthenticated ? "/login" : "/profile"}>
<a className="signinBtn mr-5">{!isAuthenticated ? "Sign In" : "My Account"}</a>
</Link>
<div className={!isAuthenticated ? "login-content" : "login-content logout-content"}>
<p> </p>
<div className="login-inner">
<Link href={!isAuthenticated ? "/login" : "/profile"} as={!isAuthenticated ? "/login" : "/profile"}><a><FontAwesomeIcon icon={faUserCircle} className="mr-2"/> Your Profile</a></Link>
<Link href={!isAuthenticated ? "/login" : "/orders"} as={!isAuthenticated ? "/login" : "/orders"}><a><FontAwesomeIcon icon={faBoxOpen} className="mr-2 orderIcon"/> Orders</a></Link>
<Link href={!isAuthenticated ? "/login" : "/wishlist"} as={!isAuthenticated ? "/login" : "/wishlist"}><a><FontAwesomeIcon icon={faHeart} className="mr-2"/> Whishlist</a></Link>
<div className="otherDrop">
{!isAuthenticated ?
<>
<p className="first">Don't have an account?</p>
<p className="register"><Link href="/register" as="/register"><a>Register</a></Link></p>
<p className="login"><Link href="/login" as="/login"><a>Login</a></Link></p>
</>
:
<p className="login"><a href="#" onClick={deauthenticate}>Logout</a></p>
}
</div>
</div>
</div>
</div>
<Link href="/cart" as="/cart">
<a className="cartBtn"><FontAwesomeIcon icon={faShoppingCart} className="mr-xl-1"/> Cart <span>{carts[0] === null ? 0 : carts.length}</span></a>
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
}
export default Header;
Layout.js
import Head from 'next/head';
import * as Main from './Index'
import './styles/Index';
const Layout = ({ children, title }) => (
<div>
<Head>
<title>{ title }</title>
<meta charSet="utf-8" />
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</Head>
<Main.Top/>
<Main.Header/>
<div>
{ children }
</div>
</div>
);
export default Layout;
next.config.js
const withSass = require('#zeit/next-sass')
module.exports = withSass({
cssLoaderOptions: {
url: false
}
})
Is there any problem with my code?
I am using sass for styling. What may be the issue. I have searched a lot and couldn't find any solution. Actually am new to next.js. So I am not able to find a solution.
As said in their docs, next/Link accept the props href and as, where:
href: The page that it should go for, this path will never change at runtime.
as: Something like a decorator, how the link should appears for the user. It can change in runtime.
Tha been said, lets take a look in one of yours Link's:
<Link href={"/products/"+trending.trending_slug} as={"/products/"+trending.trending_slug}><a>{trending.trending_name}</a></Link>
In this case your href is changing dynamic with your trending and it should be a page that exists in your project, like pages/product/trending and if trending is dynamic you can use pages/product/[trending] and then in the as property you should use the dynamic link, like you are already doing, /products/"+trending.trending_slug.
Take a look into their docs about it: https://nextjs.org/docs/tag/v9.5.2/api-reference/next/link#dynamic-routes
Here is a issue that look's to be the same problem: https://github.com/vercel/next.js/issues/11157
I am using React 16 with Bootstrap 4.
I am using bootstrap modal to display some values. I need to reset these values whenever modal is closed.
For Modal I have created a separate component. I dont want to use React-Modal as I get all the functionality in the current modal.
I know in plain javascript it is achieved using below code:
$(".modal").on("hidden.bs.modal"){
//reset values here
};
But I dont know how this is achieved in ReactJS?
Below is my code for modal:
<div className="modal fade modal-flex" id="large-Modal-OneUser" tabIndex={-1} role="dialog">
<div className="modal-dialog modal-lg" role="document">
<div className="modal-content">
<div className="modal-header" style={{display: 'block'}}>
<div className="row">
<div className="col-md-6">
<h2 style={{fontWeight:600}}>{newTimelineData.length > 0 ? newTimelineData[0].candidateName : ""}</h2>
</div>
<div className="col-md-6">
<span style={{display: 'inline-flex',alignItems: 'center',float:'right'}}><h4 style={{paddingRight:20}}>{isNotEmpty(this.state.scheduledFor) ? moment(this.state.scheduledFor).format("DD-MMM-YYYY"):this.checkScheduledFor(newTimelineData)}</h4>
<h3 style={{paddingRight: 10}}>{isNotEmpty(this.state.probability) ? this.getProbabilityHTML() : this.checkProbability(newTimelineData)}</h3>
{/*<button type="button" className="close" data-dismiss="modal" aria-label="Close" style={{marginTop: 0,marginBottom: 10}}>
<span aria-hidden="true">×</span>
</button>*/}
</span>
</div>
</div>
</div>
<div className="modal-body">
<div className="col-md-12">
{/*<div className="card">*/}
{/*<div className="card-block">*/}
{/* Horizontal Timeline start */}
<div className="cd-horizontal-timeline">
<div className="timeline">
<div className="events-wrapper">
<div className="events" id="foo">
<ol>
{newTimelineData.map((item, index) => (
<li key={item.id}>
<a
href="#0" onClick={()=> this.setHeaders(item)}
data-date={moment(item.scheduledFor).format('DD/MM/YYYY')}
className={index === 0 ? 'selected' : null}>
<Moment unix format="DD MMM">
{item.scheduledFor / 1000}
</Moment>
</a>
</li>
))}
</ol>
<span className="filling-line" aria-hidden="true" />
</div>
{/* .events */}
</div>
{/* .events-wrapper */}
<ul className="cd-timeline-navigation">
<li>
<a href="#0" className="prev inactive">
Prev
</a>
</li>
<li>
<a href="#0" className="next">
Next
</a>
</li>
</ul>
{/* .cd-timeline-navigation */}
</div>
{/* .timeline */}
<div className="events-content">
<ol>
{newTimelineData.map((item, index) => (
<li
key={item.id}
className={index === 0 ? 'selected' : null}
data-date={moment(item.scheduledFor).format('DD/MM/YYYY')}>
<div className="row">
<div className="col-sm-8" style={{fontSize:'1rem',paddingLeft: 3,paddingRight:0}}><b>Job</b> : {item.jobName}</div>
{isNotEmpty(joiningDate) && <div className="col-sm-4" style={{fontSize:'1rem',paddingLeft: 3,paddingRight:0}}><b>Joined Date : </b>{joiningDate}</div>}
</div>
<div className="row">
<div className="col-sm-8" style={{fontSize:'1rem',padding:0}}><b>Stage</b> : {this.props.stage}</div>
{isNotEmpty(offerDate) && <div className="col-sm-4" style={{fontSize:'1rem',paddingLeft: 0,paddingRight:0}}><b>Offer Date : </b>{offerDate}</div>}
</div>
<br></br>
<div className="row">
<div className="col-sm-12" style={{fontSize:'1rem',paddingLeft: 0}}><b>Comments</b> :<br></br>{item.comments}</div>
</div>
</li>
))}
</ol>
</div>
{/* .events-content */}
</div>
{/* Horizontal Timeline end */}
{/*</div>*/}
{/*</div>*/}
</div>
</div>
<div className="modal-footer">
<button style={{backgroundColor: '#8080808f',borderColor:'#8080808f'}}
type="button"
className="btn btn-primary waves-effect waves-light"
data-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>
Can anyone help?
See below snapshot for the work around I have tried suggested by #Jayavel.
Implemented a small workaround and hope it's fulfills your need, With my understanding you load your modal body with state and user will change something and you store those in the same state.
While closing the modal(close button) you need to reset the initial state i.e reset to default values.
Is that right !!! check this demo
what you need is,
store your default state like below:
const initialState = {
isOpen: false,
value: "defaultvalue"
};
and in component :
class App extends Component {
constructor(props) {
super(props);
this.state = initialState; // stored defaultstate
}
toggleModal = () => {
this.setState({
isOpen: !this.state.isOpen
});
}
toggleModalClose = () => { // modal close to reset input val
this.setState(initialState);
}
handleChange = (e) => {
this.setState({
value: e.target.value //input new value
});
}
render() {
return (
<div className="App">
<button onClick={this.toggleModal}>
Open the modal
</button>
<Modal show={this.state.isOpen}
onClose={this.toggleModalClose}>
<input type="text" value={this.state.value} onChange={this.handleChange} />
</Modal>
</div>
);
}
}
Hope this helps.