Load a react component on button onClick - javascript

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>
)

Related

How can i use useParams() with an onClick button to navigate to different pages and display the data in react.js?

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} />

add a class to an element in a .map function with useState react

<div>
{arrayCard.map((item, index) => {
return (<Card key={index}
onClick={(e) => handleClick(index, e)}
src={item} />)
})}
</div>
This is my Card component.
<button onClick={props.onClick} className="focus:outline-none">
<Image
src={props.src}
alt="Card Pic"
width={80}
height={80}
/>
</button>
This is what I have inside my component. What I want to do is add a class to the clicked Card element. Each one has a different index but I don't know what to do with it.
I have a function handleClick and a useState() to do it.
I hope you can help me with this. Thanks!
you need to change your Card Component:
const [isActive, setIsActive] = useState(false);
const handleClick = (e) => {
setIsActive(value => !value);
props.onClick(e);
}
return (
<button onClick={handleClick} className={`focus:outline-none ${isActive ? 'activeClass' : null}`}>
<Image src={props.src} alt="Card Pic" width={80} height={80} />
</button>
);

Trying to switch between modal components using React

So I have a start page that gives options to open a login modal or sign up modal. However, once you are in the login modal I give an option so you can switch to sign up modal. However, I can't seem to get this to work. The one time I got it to work, the modal showed up in the wrong section of the screen since it was being opened in relation to the login modal and not the start page.
I am new to React so any insight would be appreciated. Should I use redux, since I can't pass props from child to parent. So that way when I return to start page I can rerender with info saying that I had clicked sign-up link on the login modal.
function LoginContent(props) {
const [ open, setOpen ] = useState(false)
const { show, closeModal } = props;
function handleSubmit(e){
e.preventDefault();
}
function handleSignUpButton(){
closeModal();
console.log(open)
setOpen(!false)
console.log(open)
}
//added so that the component doesn't get affected by parent css
//and is being rendered from the "modal-root" DOM node from the index.html file
return ReactDOM.createPortal(
<>
<div className={show ? "overlay" : "hide"} onClick={closeModal} />
<div className={show ? "modal" : "hide"}>
<button onClick={closeModal} id="close">X</button>
<div className="login_form">
<h1> Log in to Continue </h1>
<form onSubmit={handleSubmit}>
<input className="username" type='text' name='username' placeholder='Email Address' />
<input className="password" type='password' name='password' placeholder='password' />
<button className="login_button"> Sign In</button>
</form>
</div>
<div className="login_demo">
<h3 className="login_demo_pointer" type="submit">Demo Login</h3>
</div>
<hr />
<div className="login_switch">Don't have an account.
<button className="signup_link" onClick={handleSignUpButton}>Sign Up</button>
{open && <SignUpContent open={open} closeModal={closeModal} show={show} />} </div>
</div>
</>, document.getElementById("modal-root")
);
}
function Start() {
const history = useHistory();
const [showLogin, setLogin ] = useState(false);
const openModalLogin = () => setLogin(true);
const closeModalLogin = () => setLogin(false);
const [showSignUp, setShow ] = useState(false);
const openModalSignUp = () => setShow(true);
const closeModalSignUp = () => setShow(false);
return (
<div className="bodyStart">
<img src="https://i.imgur.com/5gjRSmB.gif" alt="" id="bg" />
<div className="start_logo">
<img src={require("../styling/logo.png")} alt="" onClick={() => {
history.push('/home')
history.go(0)}} className="logo" />
</div>
<div className="start">
<div className="start_heading">
<h2>Mother Nature is Calling.</h2>
<h4>Find a place to recharge and escape the day to day.</h4>
</div>
<div className="start_location">
<p>Where?</p>
<div className="start_input">
<input type="text" placeholder="anywhere" />
<ArrowForwardIcon onClick={() => {
history.push('/search')
history.go(0)}}
className="arrow" fontSize="large"/>
</div>
</div>
<div className="start_authentication">
<Button className="login"
variant="contained"
color="primary"
size="large"
onClick={() => openModalLogin()}> Login </Button>
{showLogin && <LoginContent closeModal={closeModalLogin} show={showLogin} />}
<Button className="signup"
variant="contained"
size="large"
onClick={()=> openModalSignUp()}> Sign-Up </Button>
{showSignUp && <SignUpContent closeModal={closeModalSignUp} show={showSignUp} />}
</div>
</div>
</div>
)
}
I have made similar modals with Material-UI. You can change loginOpen state and signupOpen states in modals. See codepen below
Codepen
const { useState } = React;
const { Button, Dialog, DialogTitle, DialogContent, DialogActions } = MaterialUI;
function LoginDialog(props) {
const { open, setLoginOpen, setSignupOpen } = props;
const switchSignup = (event) => {
setLoginOpen(false)
setSignupOpen(true)
}
return (
<Dialog aria-labelledby="simple-dialog-title" open={open}>
<DialogTitle id="simple-dialog-title">LOGIN</DialogTitle>
<DialogContent>If you don't have an account, press SIGNUP</DialogContent>
<DialogActions>
<Button onClick={(event) => {setLoginOpen(false)}}>CLOSE</Button>
<Button>LOGIN</Button>
<Button onClick={switchSignup}>SIGNUP</Button>
</DialogActions>
</Dialog>
);
}
function SignupDialog(props) {
const { open, setLoginOpen, setSignupOpen } = props;
const switchLogin = (event) => {
setSignupOpen(false)
setLoginOpen(true)
}
return (
<Dialog aria-labelledby="simple-dialog-title" open={open}>
<DialogTitle id="simple-dialog-title">SIGNUP</DialogTitle>
<DialogContent>If you have an account, press LOGIN</DialogContent>
<DialogActions>
<Button onClick={(event) => {setSignupOpen(false)}}>CLOSE</Button>
<Button>SIGNUP</Button>
<Button onClick={switchLogin}>LOGIN</Button>
</DialogActions>
</Dialog>
);
}
const App = () => {
const [loginOpen, setLoginOpen] = useState(false)
const [signupOpen, setSignupOpen] = useState(false)
const handleLogin = (event) => {
setLoginOpen(true)
}
const handleSignup = (event) => {
setSignupOpen(true)
}
return (
<div>
<Button variant='contained' color='primary' onClick={handleLogin} >
LOGIN
</Button>
<Button variant='outlined' color='primary' onClick={handleSignup} >
SIGNUP
</Button>
<LoginDialog open={loginOpen} setLoginOpen={setLoginOpen} setSignupOpen={setSignupOpen} />
<SignupDialog open={signupOpen} setLoginOpen={setLoginOpen} setSignupOpen={setSignupOpen} />
</div>
)
}
ReactDOM.render(<App />, document.getElementById("root"));

Re-render the same component with different parameter

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]);

Edit button + populate field with redux / react

I need send the data line from DataTable to another page and populate the fields with React or Redux... how can i do that?
class Dtable extends Component {
componentWillMount() {
this.props.getList();
}
actionTemplate(rowData, column) {
return <div>
<Button type="button" icon="fa-search" className="ui-button-success"></Button>
<Button type="submit" icon="fa-edit" onClick={console.log(column)} className="ui-button-warning" ></Button>
</div>
}
render() {
return (
<div>
<Form onSubmit={this.props.create} />
<div className="content-section implementation" style={{ paddingTop: 1 + '%' }}>
<DataTable key="idPessoa" value={this.props.list} paginator={true} paginator={true} rows={10} rowsPerPageOptions={[5, 10, 20]} >
<Column field="idPessoa" header="Propriedade" style={{ width: 5 + '%' }} />
<Column field="nome" header="Propriedade" />
<Column field="email" header="Propriedade" />
<Column field="latitude" header="Relatório" style={{ width: 15 + '%' }} />
<Column field="longitude" header="Ativo" style={{ width: 5 + '%' }} />
<Column header="Opções" body={this.actionTemplate} style={{ textAlign: 'center', width: '100px' }} />
</DataTable>
</div>
</div>
)
}
}
const mapStateToProps = state => ({ list: state.upload.list })
const mapDispatchToProps = dispatch => bindActionCreators({ getList, create, showUpdate }, dispatch)
export default connect(mapStateToProps, mapDispatchToProps)(Dtable)
I just add the arrow function on my event ..this solve my problem..thanks guys.
actionTemplate = (rowData, column) => {
return <div>
<Button type="button" icon="fa-search" imediate='true' onClick={() => this.teste(rowData.nome,rowData.email)} className="ui-button-success"></Button>
<Button type="button" icon="fa-edit" imediate='true'
onClick={() => console.log(rowData)} className="ui-button-warning" ></Button>
</div>
}
teste = (nome,mail) => {
console.log(nome)
this.setState({name:nome,email:mail})
}

Categories

Resources