So i'm new to reactjs, im doing a table that when you click on 1 row it will render a detail description for that row. I have some button to trigger some event on that description table. But when i'm click the row on the table the description still render but the problem is, all the event in the descroption is trigger when i click on the row table not the button. Help pls
Here is my code:
const [displayCoursesDescription, setDisplayCoursesDescription] = useState({ coursesDescription: [] });
const handleCloseCoursesDescription = () => setDisplayCoursesDescription({ coursesDescription: [] });
const handleReloadCourse = () => {
setDisplayCoursesDescription({ coursesDescription: [] });
dispatchStudentCourses();
};
<div className="studentDashboardContent">
<div className="TableHeader">
<img className="courseIcon" src={courseActive} alt="courseActive" role="presentation" />
<p className="courseText">Courses</p>
<div className="ToolBar">
<OutlinedButton
icon={<ReloadOutlined style={{ width: '32px' }} />}
color={COLOR}
backgroundColor={BACKGROUND_COLOR}
display="inline"
onClick={handleReloadCourse}
/>
<SearchBox
placeholder="Search for courses"
color={COLOR}
backgroundColor={BACKGROUND_COLOR}
display="inline" // inline || none
/>
</div>
</div>
{courses && courses.status === API_STATUS.LOADING ? (
<LoadingIndicator />
) : (
<Table
className="studentTable"
columns={columns}
dataSource={coursesSource}
pagination={{ hideOnSinglePage: true }}
onRow={(record) => ({
onClick: (event) => {
setDisplayCoursesDescription({ coursesDescription: record });
getDepartmentById(record.department);
},
})}
/>
)}
</div>
{displayCoursesDescription.coursesDescription.key ? (
<div className="CourseDescription">
<div className="HeaderButton">
<a
href={displayCoursesDescription.coursesDescription.hostname}
className="courseUrl"
rel="noreferrer"
target="_blank"
>
<div className="forwardBtn" role="presentation">
<p className="forwardText">Go to course</p>
<img className="forwardImg" src={forward} alt="forward" />
</div>
</a>
<Button className="closeBtn" type="primary" icon={<CloseOutlined />} onClick={console.log('click1')} />
</div>
<div className="courseCodeName">
<p className="courseCode">{displayCoursesDescription.coursesDescription.code}</p>
<p className="courseName">{displayCoursesDescription.coursesDescription.name}</p>
</div>
<p className="departmentTitle">DEPARTMENT</p>
<div className="courseDepartment">
<img className="departmentImg" src={departmentIcon} alt="department" />
<p className="departmentName">{departments.name}</p>
</div>
<div className="courseDescription">
<p className="descriptionTitle">COURSE DESCRIPTION</p>
<p className="description">{displayCoursesDescription.coursesDescription.description}</p>
</div>
<Button className="unassignCourse" type="primary" danger onClick={console.log('click2')}>
Exit course <LoginOutlined />
</Button>
</div>
) : (
<div className="studentBackground">
<div className="dashboardContainer">
<p className="hiText">Hi {user.name}. How are you today?</p>
<img className="dashboardIMG" src={dashboardIMG} alt="dashboardimg" />
</div>
</div>
)}
Here is the console log that 2 onClick event were trigger when i click on the table Row
enter image description here
Related
Im trying to test a basic component that has a nested Modal component. How could one mock the Modal and test the Modal is successfully populated by values from extraDataInfo object (i.e extraDataInfo?.title)?
export const ExtraDataButtons = ({ extraDataInfo, containerClassName }) => {
const modalSeeMoreTrigger = {
ariaLabel: 'See more',
cssClassName: 'c-extra-data-see-more',
dataAttributes: { seeMore: 'seeMore' },
text: 'See more'
};
return (
<div className={containerClassName}>
<Modal trigger={modalSeeMoreTrigger}>
<div className="c-extra-data-info-cont">
<div className="c-extra-data-number">{extraDataInfo?.offerData}</div>
<div className="c-extra-data-detail">
<div className="c-extra-data-message">
{extraDataInfo?.text && (
<h3 className="c-extra-data-heading">{extraDataInfo?.text}</h3>
)}
{extraDataInfo?.offerDescription && (
<p className="c-extra-data-description">{extraDataInfo?.offerDescription}</p>
)}
</div>
</div>
</div>
<h4 className="c-extra-data-tc-heading" data-test-id="c-extra-data-tc-heading">
{extraDataInfo?.title}
</h4>
<Markdown text={extraDataInfo?.content} />
</Modal>
<button data-test-id="see-more-btn" className="c-extra-data-see-more" type="button">
<Icon svgSource={linearArrowRight} size={20} />
</button>
</div>
);
};
i have this input filed in my code for serching the list i have 3 catagery of list which are displayed by three map() i want to input a name in the input fild and if it exist i want to show the firstname just like whatsapps serach works
<form style={{ display: "flex" }}>
<input
className="w-100 msserserch gradiantblur"
placeholder="seach messages"
onChange={(e) =>
this.setState({ serchinput: e.target.value })
}
type="Search"
/>
</form>
the map() are given below there are 3 i want when i type in input fild fistname mustbe filterd from this
{this.state.tablist == "doctor" ? (
<div
className="chat-avatar gradiantblur"
onClick={() => this.livechat(this.state.list.id)}
>
<div></div>
<div className="alignstart">
{this.state.list.firstname} {this.state.list.lastname}
<p className="margin-0">
{" "}
{this.state.list.speciality}
</p>
<p className="margin-0">
✓ {this.state.list.speciality}
</p>
</div>
<div>152:11</div>
</div>
) : this.state.tablist == "consultant" ? (
<>
<div className="scrollerchatlist">
{console.log(this.state.consulatnt)}
{this.state.consulatnt.map((data) => (
<div
className="chat-avatar gradiantblur"
onClick={() => this.livechat(data.id)}
>
<div>
</div>
<div className="alignstart">
{data.firstname} {data.lastname}
<p className="margin-0"> {data.speciality}</p>
<p className="margin-0">
✓ {data.firstname}
</p>
</div>
<div>152:11</div>
</div>
))}
</div>
</>
) : this.state.tablist == "sales" ? (
<>
<div className="scrollerchatlist">
{this.state.sales.map((data) => (
<div
className="chat-avatar gradiantblur"
onClick={() => this.livechat(data.id)}
>
<div>
</div>
<div className="alignstart">
{data.firstname}
<p className="margin-0">
</p>
</div>
<div>152:11</div>
</div>
))}
</div>
</>
) : null}
my code is big so i put it in codesandbox
https://codesandbox.io/s/intelligent-nova-v7pb1?file=/src/App.js
I see in your code, you have this.state.tablist which is deciding what to render when any tab gets selected. So whenever user types in the input, you can just filter out firstname string from all three array and render them in your list:
onChange={this.onSearchTextChange}
onSearchTextChange(event) {
const query = event.query.target;
if(query){
const dataSet = [this.state.sales, this.state.consultants, ...];
const filteredName = dataSet.map(
data => data.filter(row => row.firstName).filter(Boolean)
).flat();
// now set the state with this data
this.setState({...});
}
}
I'm creating a movies app with React and Redux, in each movie card I have some information about the movie like the title, image, and a button(buy a ticket). The idea is when I click on the button of each card I want to get the same image and title of the card and display it on the same page on another card that going to pop up so the user can choose the quantity and continue.
How can I get the data from the movie card onclick and transform it to another card as a pop-up?
what do you think
Single movie card Component
const SingleMovieCard = ({ id, title, poster_path, overview, toggleHandler }) => {
const [selected, isSelected] = useState(null);
return (
<article key={id} className="card">
<div key={id} onMouseEnter={() => isSelected(id)} onMouseLeave={() => isSelected(null)}>
<img src={`${ImgPath}` + poster_path} alt={title} className="image" />
{selected === id && <video src="./Trailers/SpaceJam.mp4" autoPlay={true} loop muted />}
</div>
<div className="body-card">
<h1>{title}</h1>
<p>{`${overview.substring(0, 200)}...`}</p>
</div>
<div className="services">
<FiShare2 className="icon" />
<FiHeart className="icon" />
<div className="btn-icon-container">
<BiShoppingBag className="btn-icon" />
<button onClick={() => toggleHandler()}>Buy Ticket</button>
</div>
</div>
</article>
)
}
export default SingleMovieCard;
Pop-up movie card
const PopUpMovie = ({showClass, toggleHandler}) => {
const moviesList = useSelector((state)=> state.allMovies.movies);
return (
<div className={`pop-up-container ${showClass}`}>
<nav className="pop-up">
<GrClose className="pop-up-close" onClick={()=> toggleHandler()}/>
<div className="product-details">
<div className="img-container">
<img src="./Pictures/FreeGuy.jpg" alt="FreeGuy" />
</div>
<div className="product info">
<h1 className="title">Free Guy movie</h1>
<div className="quantity">
<h4>Quantity</h4>
<span>4</span>
</div>
<h5 className="prix">11$</h5>
<button className="btn-checkout">Continue to checkout</button>
</div>
</div>
</nav>}
</div>
)
}
export default PopUpMovie;
you can use Modal from react-bootstrap
Example:
import { Modal } from "react-bootstrap";
const PopUpMovie = ({ showClass, toggleHandler }) => {
const modalContent = (
<div className={`pop-up-container ${showClass}`}>
<nav className="pop-up">
<GrClose className="pop-up-close" onClick={() => toggleHandler()} />
<div className="product-details">
<div className="img-container">
<img src="./Pictures/FreeGuy.jpg" alt="FreeGuy" />
</div>
<div className="product info">
<h1 className="title">Free Guy movie</h1>
<div className="quantity">
<h4>Quantity</h4>
<span>4</span>
</div>
<h5 className="prix">11$</h5>
<button className="btn-checkout">Continue to checkout</button>
</div>
</div>
</nav>
</div>
)
const moviesList = useSelector((state) => state.allMovies.movies);
return (
<Modal
id="order-modal-close"
backdrop="static"
show={showClass}
size={"md"}
dialogClassName="modal-90w"
onHide={toggleHandler}
>
<Modal.Header closeButton>
<Modal.Title>Movie</Modal.Title>
</Modal.Header>
<Modal.Body >{modalContent}</Modal.Body>
{modalFooter}
</Modal>
)
}
I am trying to have a popup for editing profile information in react, and I want there to be a button by each value that will allow a user to edit that specific value. The popup works, except it will only display the last value that I have put in. I think it is because I need to reset the state each time the button is clicked, but I am still fairly new to react so I am not sure how to do it.
I will add my code, however it is pulling some information from a local database, so let me know if you need me to remove things.
Here is the component for the popup
import React from 'react'
const Popup = props => {
console.log(props)
return(
<div className='popup-box'>
<div className='box'>
<span className='close-icon' onClick={props.handleClose}>x</span>
{props.content}
</div>
</div>
)
}
export default Popup
And here is the component page where the popup appears
import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { getUser } from '../apiClient'
import Nav from './Nav'
import EditPopup from './EditPopup'
export default function UserProfile (props) {
const [isOpen, setIsOpen] = useState(false)
const togglePopup = () => {
setIsOpen(!isOpen)
}
const [user, setUser] = useState({
user: []
})
useEffect(() => {
getUser(props.match.params.id)
.then((res) => {
setUser(res)
})
.catch((error) => {
console.log('error', error.message)
})
}, [])
return (
<div className='globalBackground'>
<Nav />
<div className='UserInfoForm'>
<div className='profile-heading' >
<h1>General User Information</h1>
</div>
<div className='profile-Pic' >
<div className='profile-pic-heading'>
<h2>Profile Picture</h2>
</div>
<div className='profile-pic-display'>
<img src={user.profilePic} style={{ width: '150px', height: '150px' }}
alt=''
/>
</div>
</div>
<div className='UsernameEdit'>
<h2>Username</h2>
<p>{user.username}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Username</b>
<div className='userNameEditInput'>
<input className='usernameEdit' placeholder={user.username} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
<div />
<div className='EmailEdit'>
<h2>Email</h2>
<p>{user.email}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Email</b>
<div className='emailEditInput'>
<input className='emailEdit' placeholder={user.email} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
</div>
<div className='CountryEdit'>
<h2>Country</h2>
<p>{user.country}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Country</b>
<div className='countryEditInput'>
<input className='countryEdit' placeholder={user.country} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
</div>
<div className='RegionEdit'>
<h2>Region</h2>
<p>{user.region}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Region</b>
<div className='regionEditInput'>
<input className='regionEdit' placeholder={user.email} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
</div>
<div className='HandicapEdit'>
<h2>Handicap</h2>
<p>{user.handicap}</p>
<input type='button' value='Edit' onClick={togglePopup} />
{isOpen && <EditPopup
content={<>
<b>Edit Your Handicap</b>
<div className='handicapEditInput'>
<input className='handicapEdit' placeholder={user.handicap} />
</div>
<button>Save Changes</button>
</>}
handleClose={togglePopup}
/>}
</div>
</div>
</div>
</div>
)
}
Let me know if there's any other code needed, any help would be greatly appreciated :--)
You can remove the state from the UserProfile and move it inside the Popup Component.
import React from 'react';
const Popup = (props) => {
const [toggle, setToggle] = useState(false);
const togglePopup = () => setToggle((prevToggle) => !prevToggle);
return (
<>
<input type="button" value="Edit" onClick={togglePopup} />
{toggle && (
<div className="popup-box">
<div className="box">
<span className="close-icon" onClick={togglePopup }>
x
</span>
{props.content}
</div>
</div>
)}
</>
);
};
export default Popup;
You can then use EditPopup as below in the UserProfile.
{
<div className='UsernameEdit'>
<h2>Username</h2>
<p>{user.username}</p>
<EditPopup
content={<>
<b>Edit Your Username</b>
<div className='userNameEditInput'>
<input className='usernameEdit' placeholder={user.username} />
</div>
<button>Save Changes</button>
</>
}
/>
<div />
}
Reactjs shows this error when i open modal that is from another component
"index.js:1 Warning: findDOMNode is deprecated in StrictMode. findDOMNode was passed an instance of Modal which is inside StrictMode. Instead, add a ref directly to the element you want to reference."
I've tried alot of other solutions but none of them work in my case
my code file:
class Routes extends Component {
componentDidMount() {
console.log('Component did mount!')
}
loginModalRef = ({ handleShow }) => {
this.showModal = handleShow;
}
onLoginClick = () => {
this.showModal();
}
ShopersModalRef = ({ handleShoperShow }) => {
this.showShoperModal = handleShoperShow;
}
onShopersClick = () => {
this.showShoperModal();
}
//ChargeModalRef = ({ handleChargeShow }) => {
// this.showChargeModal = handleChargeShow;
//}
// onChargeClick = () => {
// this.showChargeModal();
// }
render() {
return (
<div>
{/*<chargeFeeModal ref={this.ChargeModalRef}></chargeFeeModal>*/}
<FormModal ref={this.loginModalRef}></FormModal>
<ShopersModal ref={this.ShopersModalRef}></ShopersModal>
<AppBar position="sticky" className="appbar">
<Toolbar className="NavbarTop">
<div className='row w-100'>
<div className="col-4 LogoOrBack">
<section className="leftBox shopname ml-4">
<Typography className="typography">
{Text}
</Typography>
</section>
</div>
<div className="col-4 centered">
<section className="centerBox">
<Typography className="typography">
<b>Stores</b>
</Typography>
</section>
</div>
<div className="col-4 righted">
<section className="rightBox">
<Typography className="typography">
<Button className="primary btn AccountBtn" onClick={this.onLoginClick}>
<img alt="user account avatar" src={require('../../../assets/images/placeholder_account.png')} className="buttonImage" /> Account
</Button>
<Button className="primary btn" onClick={this.onLoginClick}>
<i className="fa fa-cart-plus cart"></i>
</Button>
</Typography>
</section>
</div>
</div>
</Toolbar>
<Toolbar>
<div className='row w-100'>
<div className='col-lg-4'>
{(() => {
//Javascript for changing buttons
switch (history.location.pathname) {
case "/": return <Button onClick={this.onLoginClick} className="primary postalCodeBtn" >
<img alt="home icon" src={require('../../../assets/images/homeicon.png')} className="buttonImage" /> <b>M4b 146, CA</b> <i className="fa fa-chevron-down downIco"></i>
</Button>;
default: return (
<Button onClick={this.onShopersClick} className="primary postalCodeBtn" >
<img alt="home icon" src={require('../../../assets/images/time.png')} className="buttonImage" /> <b style={{ textTransform: 'capitalize' }}>Shoppers Occupied</b>
</Button>
);
}
})()}
</div>
<div className="col-lg-4 centered p-1 pl-4" >
<div className="searchContainer">
<i className="fa fa-search searchIcon"></i>
<input className="searchBox" type="search" name="search" placeholder="Search Stores" />
</div>
</div>
{TabsShowOrNo}
</div>
</Toolbar>
</AppBar>
<AnimatedSwitch
atEnter={{ opacity: 0 }}
atLeave={{ opacity: 0 }}
atActive={{ opacity: 1 }}
className="switch-wrapper"
>
<Route exact path="/" component={HomePage} />
<Route path='/store/orders/' component={OrdersPage} />
<Route path='/store/aisles/' component={AislesPage} />
<Route path="/store/featured" component={SingleStorePage} />
<Route component={NotFound} />
</AnimatedSwitch>
</div >
)
}
}```
any help will be appreciate