How can I toggle between states of a button in React? - javascript

I'm using Material UI for the icons for connect and disconnect.
I want the application to swap between these two icons onClick.
I'm new to React, but haven't any helpful resources yet.
Here's the code as it is so far:
{ user.connected ?
(
<Button color="info" simple size="sm">
<PersonAddDisabled className={classes.footerIcons} /> Disconnect
</Button>
)
:
(
<Button color="info" size="sm">
<PersonAdd className={classes.footerIcons} /> Connect
</Button>
)
}
As it is above, I am address whether they are connected or not, but I'm not sure how to implement a toggle of those two buttons, where onClick it will switch between the two.

here is a code
Your state
state = {
connected: true
}
onClickButton(){
this.setState(prevState => {connected: !this.prevState.connected})
}
Your code
{ this.state.connected ?
(
<Button color="info" simple size="sm" onClick={ this.onClickButton }>
<PersonAddDisabled className={ classes.footerIcons } /> Disconnect
</Button>
)
:
(
<Button color="info" size="sm" onClick={ this.onClickButton }>
<PersonAdd className={ classes.footerIcons } /> Connect
</Button>
)
}

Related

React JS- Multiple Buttons

I'm trying to make multiple toggles buttons, and whenever the user clicks on any one of them, then I want it to become a bit darker. So, that user knows which one they've clicked.
Here's sample code I've written.
CODE:
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [active, setActive] = useState("first");
return (
<>
<div className="App">
<button className="button" active={active === "first"} onClick={() => {setActive("first"); }} >first</button>
<button className="button" active={active === "Second"} onClick={() => {setActive("Second"); }} >Second</button>
<button className="button" active={active === "Third"} onClick={() => {setActive("Third"); }} >Third</button>
</div>
</>
);
}
Now, How do I make an OnClick function that holds the after Click? functionality?
You can do it like this:
<button
className={`button ${active === "first" ? "activeButton" : ""}`}
onClick={() => {
setActive("first");
}}
>
first
</button>
<button
className={`button ${active === "Second" ? "activeButton" : ""}`}
onClick={() => {
setActive("Second");
}}
>
Second
</button>
<button
className={`button ${active === "Third" ? "activeButton" : ""}`}
onClick={() => {
setActive("Third");
}}
>
Third
</button>
And then in you css file:
.activeButton {
background-color: red;
}

Bootstrap React Modal Component not working dynamically

I am using React Bootstrap, I am using map function of javascript to loop through admins, when i loop through them all values outside the modal display the correct values from the admins array, but inside the modal it shows only one standard object from the array everytime. The id of that component is different outside the modal and inside the modal, the modal inside displays only the user with id 1 in every component or every time the modal is clicked
admins = [ {id: 5, email: "angelinsneha#gmail.com", name: "angelin", role: "admin"},
{id: 4, email: "angelinsneha14#gmail.com", name: "angu", role: "admin"},
{id: 1, email: "angelin#gmail.com", name: "aanjuu", role: "admin"}]
<div className="rgtss pb-5">
{admins.length > 0
? admins.map((i) => (
<div className="bdr">
<div>
<p>{i.name} {i.id}</p>
<span>{i.email}</span>
</div>
<div className="mt-3">
<p>{i.role}</p>
</div>
<div>
<DropdownButton
id="dropdown-basic-button"
variant="dark"
title=""
size="sm"
>
<Dropdown.Item href={id == i.id ? "/profile" : ""}>
Edit
</Dropdown.Item>
{4 == i.id ? (
""
) : (
<Dropdown.Item onClick={handleShow}>Delete {i.id}</Dropdown.Item>
)}
</DropdownButton>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Delete Account {i.id}</Modal.Title> // only id 1 is displayed in modal, everytime the loop runs
</Modal.Header>
<Modal.Body>
Are you sure you want to delete this team account:{" "}
<b>{i.name}</b>?
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button
variant="danger"
onClick={() => handledelete(i.id)}
>
Delete
</Button>
</Modal.Footer>
</Modal>
</div>
</div>
))
: ""}
</div>
I have no idea why this is happening, can you'll help me?
You're creating modals in a loop (in this case, 3), which is not best practice for this very problem. You'd expect that each modal has the right props depending on the item of the array, but then how does the code know which modal to display ?
Your <Modal> should be outside the loop. Store a variable to know which admin to display when the modal is brought up. (It could be the index in the array, or adding a selected boolean to the admin).
When you trigger your handleShow, set this variable as well (don't forget to unset it when you're done, to prevent side-effects)
You should also use === instead of == unless it's really intended (see this SO post for more info)
EDIT: In code, it should look like this (don't copy/paste, it is untested)
const MyComponent = () => {
const [adminSelected, setAdminSelected] = useState(-1);
return (
<div className="rgtss pb-5">
{admins.length > 0
? admins.map((i, idx) => (
<div className="bdr">
<div>
<p>
{i.name} {i.id}
</p>
<span>{i.email}</span>
</div>
<div className="mt-3">
<p>{i.role}</p>
</div>
<div>
<DropdownButton
id="dropdown-basic-button"
variant="dark"
title=""
size="sm"
>
<Dropdown.Item href={id === i.id ? '/profile' : ''}>
Edit
</Dropdown.Item>
{4 === i.id ? (
''
) : (
<Dropdown.Item onClick={() => {
setAdminSelected(idx);
handleShow();}}>
Delete {i.id}
</Dropdown.Item>
)}
</DropdownButton>
</div>
</div>
))
: ''}
<Modal show={show} onHide={() => {
setAdminSelected(-1);
handleClose();}}>
<Modal.Header closeButton>
<Modal.Title>Delete Account {i.id}</Modal.Title> // only id 1 is
displayed in modal, everytime the loop runs
</Modal.Header>
<Modal.Body>
Are you sure you want to delete this team account: <b>{i.name}</b>?
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="danger" onClick={() => handledelete(i.id)}>
Delete
</Button>
</Modal.Footer>
</Modal>
</div>
);
};
Note that I added the idx variable in mapping to know which admin has been clicked (-1 for none), and I'm setting it along with the handleShow method.

Button doesn't work if I use template literals to toggle CSS classes in React

I have a CSS module called styles and this React code. It's a div with two buttons inside. I use the isMenuActive state to verify if the menu is active or not. If it is active, the CSS class 'active' gets in and the menu appears, otherwise not.
<div className={`${styles.customerOptionsMenu} ${isMenuActive ? styles.active : null}`}>
<button onClick={() => { console.log('hi') }}>
<span className="material-icons">edit</span>Editar
</button>
<button onClick={() => {console.log('hi')}}>
<span className="material-icons">delete</span>Deletar
</button>
</div>
When I click the buttons, nothing happens.
But If I store the button as a global variable in developer tools and run button.click() it works fine if I remove the template literals:
<div className={styles.customerOptionsMenu + styles.active}>
<button onClick={() => { console.log('hi') }}>
<span className="material-icons">edit</span>Editar
</button>
<button onClick={() => {console.log('hi')}}>
<span className="material-icons">delete</span>Deletar
</button>
</div>
It works fine.
Why??? And what should I do to keep changing the classes when isMenuActive changes?
Edit: Full code with the button that changes isMenuActive
const [isMenuActive, setIsMenuActive] = useState(false)
const onBlur = () => { setIsMenuActive(!isMenuActive)}
return(
<td>
<button onBlur={onBlur} className={styles.customerOptions} onClick={() => setIsMenuActive(!isMenuActive)}>
<span className="material-icons">more_horiz</span>
</button>
<div className={`${styles.customerOptionsMenu} ${isMenuActive ? styles.active : null}`}>
<button onClick={() => { console.log('hi') }}>
<span className="material-icons">edit</span>Editar
</button>
<button onClick={() => {console.log('hi')}}>
<span className="material-icons">delete</span>Deletar
</button>
</div>
</td>
)
New edit: The answer is in the comments by Pandaiolo. The problem was the onBlur={onBlur} code, when I removed it from the button everything worked fine!
To handle changing classnames you can use the classnames package to do something like this:
import cx from "classnames";
<div className={cx(styles.customerOptionsMenu, { styles["active"]: isMenuActive })}>
<button onClick={() => { console.log('hi') }}>
<span className="material-icons">edit</span>Editar
</button>
<button onClick={() => {console.log('hi')}}>
<span className="material-icons">delete</span>Deletar
</button>
</div>
I think the space is fine in your template literal, because it references two different class names. You probably want to use ${isMenuActive ? styles.active :''} otherwise null becomes the string "null", which is probably harmless unless you have a class .null that applies some styles, but that is basically not what you want.
But maybe the onBlur is called after the click?
click
button becomes focus
button blurs ?
Not sure. But in that case it would toggle the state two times, cancelling its effect. Maybe try with just the onClick and without the onBlur at first?
And you can add a console.log('isMenuActive', isMenuActive) before the return statement to see it's value along rerenders, see if it matches what you expect.
The isMenuActive is not defined. Place it in as a parameter as so:
export default function App(isMenuActive) {
return (
<div className="App">
<div className={`${styles.customerOptionsMenu} ${isMenuActive ? styles.active : null}`}>
<button onClick={() => { console.log('hi') }}>
<span className="material-icons">edit</span>Editar
</button>
<button onClick={() => {console.log('hi')}}>
<span className="material-icons">delete</span>Deletar
</button>
</div>
</div>
);
}

React How to change view after click on button

I wouldlike to change my view when I click on one Button :
render(){
return(
<div className="button-toolbar">
<button className="button">Button 1</button>
<button className="button">Button 2</button>
<button className="button">Button 3</button>
<View1></View1>
<View2></View2>
<View3></View3>
</div>
)
For example when I click on the button 1, only View1 is active.
If I click on Button 2 ==> View 2
If I click on Button 3 ==> View 3
PS : View1, View2 and View3 are component file (.jsx)
There are multiple ways to do this. You can set flags around the views. For example
render(){
return(
<div className="button-toolbar">
<button className="button" onClick={() => setState({view: 1})}>Button 1</button>
<button className="button" onClick={() => setState({view: 2})}>Button 2</button>
<button className="button">Button 3</button>
{this.state.view === 1 ? <View1></View1> : ''}
{this.state.view === 2 ? <View2></View2> : ''}
<View3></View3>
</div>
)
Do it like this:
render(){
return(
<div className="button-toolbar">
<button className="button" onClick={() => setState({view: 1})}>Button 1</button>
<button className="button" onClick={() => setState({view: 2})}>Button 2</button>
<button className="button" onClick={() => setState({view: 3})}>Button 3</button>
{this.state.view === 1 ? <View1/> :this.state.view === 2? <View2/>:this.state.view === 3?<View3/>:''}
</div>
)
If you're using class approach you could do something like this
class Test extends React.Component {
state = {
currentView: 1
}
setCurrentView(viewNumber) {
this.setState({ currentView: viewNumber });
}
render(){
return(
<div className="button-toolbar">
<button
className="button"
onClick={() => this.setCurrentView(1)}
>Button 1</button>
// in the rest just change the number
{
this.state.currentView === 1
? <View1/>
: // (and so on)
}
</div>
)
You can create a simple array to generate buttons and add method to class to remove this part
{
this.state.currentView ...
}
from jsx.
Before next questions like this, please visit official React docs.
This can be achieved in multiple ways.
Achieving it using hooks approach (using state)
Use the react's useState - active .
Active View will be decided based upon the value of active value. Thus creating the reactivity b/w active and the view to be rendered.
I have created a sample code in codesandbox . You can refer - Link
const [active, setActive] = React.useState(1);
const SetView = (active) => {
setActive(active);
};
const ActiveView = () => {
switch (active) {
case 1:
return <View1 />;
case 2:
return <View2 />;
default:
return <View3 />;
}
};
return (
<div className="button-toolbar">
<button className="button" onClick={() => SetView(1)}>
Button 1
</button>
<button className="button" onClick={() => SetView(2)}>
Button 2
</button>
<button className="button" onClick={() => SetView(3)}>
Button 3
</button>
{ActiveView()}
</div>
);
You can learn more about the React Hooks in the article - https://reactjs.org/docs/hooks-intro.html

conditional passing component as array prop in react

How can I conditionally pass the footer's button component? cancelBtnBasicModal and okBtnBasicModal the button is still there without text label.
Below is a modal component, it worked, but if I don't pass in
render() {
const { titleBasicModal, showBasicModal, handleOkBasicModal, handleCancelBasicModal,
contentBasicModal, cancelBtnBasicModal, okBtnBasicModal, loading } = this.props
return (
<div>
<Modal
visible={showBasicModal}
title={titleBasicModal}
onCancel={handleCancelBasicModal}
footer={[
<Button onClick={handleCancelBasicModal}>
{cancelBtnBasicModal}
</Button>,
<Button key="submit" type="primary" size="large" loading={loading} onClick={handleOkBasicModal}>
{okBtnBasicModal}
</Button>
]}
>
{contentBasicModal}
</Modal>
</div>
);
}
I tried
footer={[
{cancelBtnBasicModal && <Button onClick={handleCancelBasicModal}>
{cancelBtnBasicModal}
</Button>},
<Button key="submit" type="primary" size="large" loading={loading} onClick={handleOkBasicModal}>
{okBtnBasicModal}
</Button>
]}
But won't work coz footer prop accept array.
You need to pass an Array, spread operation is for rescue.
You can do something like that:
footer={[
...(cancelBtnBasicModal ? [
<Button onClick={handleCancelBasicModal}>
{cancelBtnBasicModal}
</Button>]: []),
<Button key="submit" type="primary" size="large" loading={loading} onClick={handleOkBasicModal}>
{okBtnBasicModal}
</Button>
]}
You can separate that logic by setting an array footerBtns with the default button (okBtnBasicModal in this case) and then we add the next button if it's passed through props.
Finally assign footerBtns to footer in the Modal component.
render() {
const { titleBasicModal, showBasicModal, handleOkBasicModal,
handleCancelBasicModal, contentBasicModal, cancelBtnBasicModal,
okBtnBasicModal, loading } = this.props
let footerBtns = [
<Button key="submit" type="primary" size="large" loading={loading}
onClick={handleOkBasicModal}>
{okBtnBasicModal}
</Button>
]
/* using unshift to add the button to the beginning of the Array */
cancelBasicModal && footerBtns.unshift(
<Button onClick=
{handleCancelBasicModal}>{cancelBtnBasicModal}
</Button>
);
return (
<div>
<Modal
visible={showBasicModal}
title={titleBasicModal}
onCancel={handleCancelBasicModal}
footer={footerBtns}>
{contentBasicModal}
</Modal>
</div>
);
}
More info on using unshift()

Categories

Resources