Disable button after click in React - reactjs

I have this piece of code but can't work out how I can disable the button after Pay is clicked:
} else if (paymentMethod.name === "Pay by Cash") {
return (
<Tab.Pane eventKey={paymentMethod.id} key={key}>
<h6 className="mb-3 mt-0 mb-3">Cash</h6>
{this.state.paymentMethodSelectionError && this.state.paymentMethodSelectionError !== "" && <Alert key="error_div" variant="danger">{this.state.paymentMethodSelectionError}</Alert>}
<p>You are paying by cash</p>
<Form.Group className="mb-0">
<Button className="btn btn-success btn-block btn-lg"
onClick={() => {
this.setState({
selectedPaymentMethod: "not-charged",
paymentGateway: paymentMethod.id
}, () => {
this.setPaymentMethod()
})
}}>
PAY £{this.state.totalPay}<Icofont icon="long-arrow-right" /></Button>
</Form.Group>
</Tab.Pane>)
Any help is appreciated

You can put a state for disabling your button:
this.state = {
disabled: false
}
In click function, change it to true:
const clickButton = () => {
this.setState({ disabled: true });
}
Then change your HTML to something like this:
<button type="button" disabled={ this.state.disabled }>Click Me!</button>
Preview:
Here

Declare a new state variable to take care of the disabled button:
const [buttonState,setButtonState]=useState(false)
Attach a onClick handler to disable the button and also manage the disabled property of the button.
<button onClick={()=>{ setButtonState(true)}} disabled={buttonState}> PAY </button>

You can use state to control the button state
Preview for both Functional and Class components
Codesandbox Preview Link

Related

I make a button base on a state, but how to make them listen to different event in React?

I'm currently working on a small project
I rendered a button base on a state like these two images,
edit button
save change button
here is my code: but everytime when I click on the edit button it will automatically run the submit button too and the isEdit state can never change to true, like this, problem, please let me know how to solve it. thanks!
const [isEdit, setIsEdit] = useState(true)
return(
...
{isEdit ? (
<button
className="btn btn--fill-primary"
type="submit"
disabled={isLoading}
onSubmit={() => {
console.log("submit")
setIsEdit(false)
}}
>
save change
</button>
) : (
<button
className="btn btn--fill-black"
type="button"
disabled={isLoading}
onClick={() => {
console.log("click")
setIsEdit(true)
}}
>
edit
</button>
)}
)
at first I render the button like this:
<button
className={`btn btn--fill-${isEdit ? "primary" : "black"}`}
type={isEdit ? "submit" : "button"}
disabled={isLoading}
onClick={(e) => {
if (isEdit) {
console.log('submit')
setIsEdit(false)
}
if (!isEdit) {
console.log('click')
setIsEdit(true)
}
>
{isEdit ? "save change" : "edit"}
</button>

Update useState onclick not updating

I am trying to update a useState object, my goal is to toggle the buttons and keep which button is on and which is off in the useState.
const SalesChartCard = (data) => {
const [toggleButton, toggleButtons] = useState({
'impressions': true,
'purchasestart': true,
'purchasecancel': true,
'purchasecomplete': true
});
const buttonClick = (dimension) => {
toggleButtons({
dimension: !toggleButton.dimension
});
};
return (
<>
<Button
outline={toggleButton.impressions}
onClick={e => buttonClick('impressions')}
color="primary" className="mb-2">
Impressions
</Button>
<Button
outline={toggleButton.purchasestart}
onClick={e => buttonClick('purchasestart')}
color="secondary" className="mb-2">
Purchase Start
</Button>
<Button
outline={toggleButton.purchasecancel}
onClick={e => buttonClick('purchasecancel')}
color="danger" className="mb-2">
Purchase Cancel
</Button>
<Button
outline={toggleButton.purchasecomplete}
onClick={e => buttonClick('purchasecomplete')}
color="success" className="mb-2">
Purchase Complete
</Button>
</>
);
};
export default SalesChartCard;
The useState react hook doesn't shallow merge state updates, you need to manage this yourself.
For the given click handler: onClick={e => buttonClick('impressions')}
The buttonClick callback handler should merge existing state and use dynamic (computed property name) keys for updating the correct property. Use a functional state update to correctly compute the next state from the previous state. This ensures all previous state updates are correctly merged when updated.
const buttonClick = (dimension) => {
toggleButtons(prevState => ({
...prevState,
[dimension]: !prevState[dimension],
}));
};
Your state is an object. When you update an object you need to keep the previous value as well. So instead of creating a new object with your dimension key you have to use object spread to keep the previous state.
Besides that as your key is in a variable you need to use key inside [].
You can do something like this,
const SalesChartCard = (data) => {
const [toggleButton, toggleButtons] = useState({
'impressions': true,
'purchasestart': true,
'purchasecancel': true,
'purchasecomplete': true
});
const buttonClick = (dimension) => {
toggleButtons({
...toggleButton,
[dimension]: !toggleButton[dimension]
});
};
return (
<>
<Button
outline={toggleButton.impressions}
onClick={e => buttonClick('impressions')}
color="primary" className="mb-2">
Impressions
</Button>
<Button
outline={toggleButton.purchasestart}
onClick={e => buttonClick('purchasestart')}
color="secondary" className="mb-2">
Purchase Start
</Button>
<Button
outline={toggleButton.purchasecancel}
onClick={e => buttonClick('purchasecancel')}
color="danger" className="mb-2">
Purchase Cancel
</Button>
<Button
outline={toggleButton.purchasecomplete}
onClick={e => buttonClick('purchasecomplete')}
color="success" className="mb-2">
Purchase Complete
</Button>
</>
);
};
export default SalesChartCard;

React toggle className on button click

I wanna change my layout between grid and list with 2 buttons. I am very new to react, and I thought to use State, my button logic seems to work(when i console.log) but I don't know how to change div classNames based on State. I tried something but it doesnt work(see below). Whatever button I click grid or list my style changes but only for the first click, then nothing happens.
const Restaurants = () => {
const [isGrid, layoutToggle] = useState({
value: true
});
console.log(isGrid);
return (
<div className="restaurants">
<button onClick={() => layoutToggle({ isGrid: true })}>
Grid
</button>
<button onClick={() => layoutToggle({ isGrid: false })}>
List
</button>
<div className={isGrid["value"] ? "layout-grid" : "layout-list"}>
{restaurants.map(restaurant => (
<Restaurant/>
))}
</div>
</div>
);
};
The problem is in the button elements, You should the change the state with the value property not the isGrid property.
<button onClick={() => layoutToggle({ value: true })}>
Grid
</button>
<button onClick={() => layoutToggle({ value: false })}>
List
</button>

my onclick function overlapped with submit handler

when i put onClick event the form does not validate and if i delete onClick event the form does not want to submit
so recently i just start a new project with kendo react. on this project i tried to create customize grid where i can add new lines, edit or remove.
<form style={{ width: '1000px' }} onSubmit={this.handleSubmit} >
<div className="col-lg-3 col-md-3 col-sm-3 col-xs-3">
<div className="k-animation-container">
<DropDownList
defaultValue={this.state.productInEdit.Programto || ''}
onChange={this.onDialogInputChange}
name="Programto"
required={true}
data={this.prog}
/>
</div>
</div>
</div>
<div className="row" >
<DialogActionsBar>
<Button
className="k-button"
onClick={this.props.cancel}
>
Cancel
</Button>
<Button className="mt-3" type="submit" primary={true} onClick={this.props.save} > Save </Button>
</DialogActionsBar>
</div>
</form>
and this is the event for validation
handleSubmit = (event) => {
event.preventDefault();
this.setState({ success: true });
setTimeout(() => { this.setState({ success: false }); }, 3000);
}
and submit code i create it on different page, so i need to call the event with this.props.save;
save = () => {
const dataItem = this.state.productInEdit;
const products = this.state.products.slice();
if (dataItem.ProductID === undefined) {
products.unshift(this.newProduct(dataItem));
} else {
const index = products.findIndex(p => p.ProductID === dataItem.ProductID);
products.splice(index, 1, dataItem);
}
this.setState({
products: products,
productInEdit: undefined
});
}
i tried to call save event inside the handleSubmit but still not working

Bootstrap 4 dropdown in react - toggle and close on click outside component

I do want to use Bootstrap 4 in react natively (without 3rd party libs). The dropdown toggle (especially closing the dropdown-menu) must be controlled by a dedicated function. The reason is that the dropdown-menu must be able to receive multiple click events. The normal behavior by BS is that it's closing after the first click.
Bootstrap Documentation suggests to use $('.dropdown-toggle').dropdown() when using JavaScript but I'd prefer not to use jQuery and refs in react.
The following code is working but I doubt it is good practice. What's the best practice solution here?
toggleDropdown = () => {
document.getElementById("dropdownMenu").style.display = document.getElementById("dropdownMenu").style.display === "" ? "block" : "";
};
render() {
<div className="dropdown">
<button
onClick={this.toggleDropdown}
className="btn btn-secondary dropdown-toggle"
type="button"
id="dropdownMenuButton">
Dropdown button
</button>
<div id="dropdownMenu" className="dropdown-menu p-4 text-muted" style={{maxWidth: "200px"}}>
<p>Some example text that's free-flowing within the dropdown menu.</p>
</div>
</div>
}
First thought: ToggleDropdown can be written like this(more dynamic).
toggleDropdown = (e) => {
var elem = e.target.nextElementSibling.classList;
elem.contains('show') ? elem.remove('show') : elem.add('show');
};
This involves the basic usage of state in React.
class App extends React.Component {
state = {
show: false,
};
render() {
return (
<div className="dropdown">
<button
onClick={() => this.setState((prevState) => ({ show: !prevState.show }))}
className="btn btn-secondary dropdown-toggle"
type="button"
id="dropdownMenuButton"
>
Dropdown button
</button>
{this.state.show && (
<div
id="dropdownMenu"
className="dropdown-menu p-4 text-muted"
style={{ maxWidth: '200px' }}
>
<p>Some example text that's free-flowing within the dropdown menu.</p>
</div>
)}
</div>
);
}
}

Resources