How can I set the timeout for the button to be disabled immidetaly after it was clicked to avoid people signing up twice?
Currently I have a function below:
timeout_init = () => {
setTimeout("timeout_trigger()", 2000);
};
<button
className="button__submit"
type="submit"
onClick={this.timeout_init}
>Submit
</button>
How can I add a disabling button into that?
Thanks
In React you should use states to keep track wether something should be disabled or not.
In example below I use the isDisabled state to disable or enable the button. Whenever the button is clicked setIsDisabled is set to true and therefor the button will now be disabled.
I don't know why you would need a setTimeout as you state "..to be disabled immediately after it was clicked..". This does just that.
const ExampleComponent = () => {
const [isDisabled, setIsDisabled] = useState(false);
const handleClick = () => {
setIsDisabled(true);
};
return (
<button
className="button__submit"
type="submit"
onClick={handleClick}
disabled={isDisabled}
>
Submit
</button>
)
};
The "disabled" state of the button is just that... state. You'd track it like any other state, for example:
// using hooks
const [isDisabled, setIsDisabled] = useState(false);
// OR if you're using old class-based components
this.state = { isDisabled: false };
And use it in the component:
<button
className="button__submit"
type="submit"
onClick={this.timeout_init}
disabled={isDisabled}
>
Submit
</button>
And you can update that state in your click handler:
// using hooks
timeout_init = () => {
setIsDisabled(true);
setTimeout(timeout_trigger, 2000);
};
// OR if you're using old class-based components
timeout_init = () => {
this.setState({ isDisabled: true });
setTimeout(this.timeout_trigger, 2000);
};
It's not clear what timeout_trigger is, but if that's where you'd want to re-enable the button then you'd setIsDisabled(false) in that function as well.
Instead of disable a button add a overlay on click on login button.
If the request is failed remove the overlay so that user can change username/password in the login form.
I the request is success, any how user will be redirected to new page.
use the event object to capture the button element then disable it after you call the setTimeOut(yourCb):
const Btn = (props) => {
const cb =() => {
console.log("Testing the button")
}
const timeout_init = (e) => {
setTimeout(cb, 2000);
e.target.disabled = true
}
return (
<button onClick={timeout_init}> Click to disable </button>
)
}
ReactDOM.render(<Btn/>,document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>
Related
1). There is a form with "Save" button
2). When user clicks save - I want the button to be disabled till backend code sends a response that the form was saved successfully.
3). The button should be enabled back after backend provides response
Why do i need this change:- when user clicks on save multiple times(say n) at once - the backend function for same data gets called for n times and data is saved n times. Hence what to handle this - please suggest
Code:
<CustomButton
save={(e) => console.log('Submitting form...')}
class='ml-2'
/>
CustomButton code:
const CustomButton = (props) => {
let className = "button btn btn-sm";
if (props.class) className += ` ${props.class}`;
else className += " mr-2";
return (
<>
{props.save ?
<Button
className={className}
id="button_success"
type="submit"
onClick={e => props.save(e)}
disabled={props.disable ? props.disable : false}
>
Save
</Button>
:
not familiar with react
A good pattern for this is to handle the disabled/enable outside of the button.
const usage = () => {
const [isLoading, setIsLoading] = useState(false);
const doRequest = () => {
setIsLoading(true);
doTheThing().then(() => {
// handle request here
}).finally(() => {
setIsLoading(false);
});
}
return (<CustomButton
save={() => doRequest()}
disable={isLoading}
class='ml-2'
/>);
}
I am trying to show a message when user try to leave current page, so I am using history.block like this:
import { useHistory } from "react-router-dom";
const ProfilerCreate = ({ pageType }) => {
const history = useHistory();
const [isDisabled, setIsDisabled] = useState(true);
const [openModalUnsave, setOpenModalUnsave] = useState(false);
useEffect(() => {
history.block(validateChange);
}, []
);
//Function to validate changes and open modal
function validateChange(txt) {
if (!isDisabled) {
toggleModalUnsave();
return false;
}
}
//Function to open or close modal
function toggleModalUnsave() {
setOpenModalUnsave(!openModalUnsave);
}
//Function to return landing page
function returnPage() {
history.push("/");
}
return (
...
<div style={{ display: "none" }}>
<Modal
id="myModal"
heading="You have unsaved changes"
description="Do you want to save or discard them?"
isOpen={openModalUnsave}
onRequestClose={(detail) => toggleModalUnsave()}
actionsRight={
<>
<Button display="text" onClick={() => returnPage()}>
Discard
</Button>
<Button
display="primary"
onClick={(evt) => saveAudienceData(evt)}
>
Save and exit
</Button>
</>
}
>
<p>Modal Children</p>
</Modal>
</div>
);
export default ProfilerCreate;
when it is detecting unsaved changes, it shows a modal with a warning and two buttons, one for save and the other for discard, when the user hit discard button it should return to home page, but history.push is not working.
I tried to find the solution or I don't know if I am using the history.block in a wrong way.
I hope that you can help me, thanks!
I think you are missing the unblock() method in validateChange(txt)
so here is what i'm trying to do. I have 3 buttons in material ui and I gave each one of them and id. I want to send the id through a onClick to a single handleclick function that then runs a switch case and determines which button pressed the id and then sets the state accordingly. This is because I want to have so when a button is clicked, it sets a key value that i specifiy depending on which one what clicked. Here is my code below
const [key, setKey] = useState("");
const handleClick = (e: MouseEvent<HTMLElement>) => {
const target = e.target as Element;
const id = target.id;
alert(id);
};
async function register(e: Event) {
e.preventDefault();
try {
const registerData = {
firstName,
lastName,
username,
password,
passwordVerify: passwordConfirm,
key: { key },
};
} catch (err) {
console.error(err);
}
}
<Button
id="btn1"
className={classes.buttonStyle}
onClick={handleClick}
>
Student
</Button>
<Button
id="btn2"
className={classes.buttonStyle}
onClick={handleClick}
>
{" "}
Ta{" "}
</Button>
<Button
id="btn3"
className={classes.buttonStyle}
onClick={handleClick}
>
{" "}
Admin{" "}
</Button>
My problem is that whenever I click the button on the react page, it shows an empty alert sometimes and other times it shows up with the button. Idk why that's the case. the alert is to test if i'm actually getting an id from the button press.
can someone tell me the types I need to be adding for this to work. Thanks
It should be as follows. The correct event triggered is a mouseEvent.
You can access Id with event.currentTarget instead of event.target
import { MouseEvent } from 'react';
...
const handleClick = (e: MouseEvent<HTMLElement>) => {
const id = e.currentTarget.id;
console.log(id);
}
...
<Button
...
onClick={handleClick}
/>
...
Change Event type to MouseEvent<HTMLButtonElement>
import { MouseEvent } from 'react'
// ... some code
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
const id = e.currentTarget.id;
console.log(id);
}
Further, for a small performance gain, it is better to declare handleClick using useCallback
import { useCallback, MouseEvent } from 'react'
// ... more code
const handleClick = useCallback((e: MouseEvent<HTMLButtonElement>) => {
const id = e.currentTarget.id;
console.log(id);
}, []);
Edit: modify answer after question edits.
so I was getting an empty alert because of the setKey line. Once I removed it, the alert showed the right key (along with changing target to currentTarget. Thanks everyone for the help
I'm relatively new to React and I was working on a button that duplicates a component I created when clicked, but I want to limit the user to only be allowed to click on said button a set number of times (say 4 times) before the button is non-functional/removed. Here's a code snippet if it helps; is this possible? I thought about having a counter, but how would I implement that alongside the button?
Many thanks!
function App() {
const [inputList, setInputList] = useState([]);
const onAddBtnClick = event => {
setInputList(inputList.concat(<Autocomplete items={foods} />));
};
return (
<Fragment>
<div className="foodcompleter">
<Button onClick={onAddBtnClick} variant="primary" size="lg" block>Add Food</Button>
{inputList}
</div>
</Fragment>
);
}
You can basically check if inputList.length === 4, then you disable the button
You can create your component CustomButton with a state that saves the number of clicks and after each state change just validate if the number of clicks is equal to your desired value.
You could remove the event listener after the click
const onKeyDown = (event) => { console.log(event) }
useEffect(() => {
window.addEventListener('keydown', onKeyDown)
return () => { window.removeEventListener('keydown', onKeyDown) }
}, [])
i have a redux form which is have a submit button and a clear button. The clear button is dispatching the reset function which is given as a property in redux form.My code is here:
<UsernameField
name={NEW_USERNAME}
onBlurFn={e => checkUsername(e.target.value)}
/>
<button className="gray" type="button" onClick={clearUsernameForm}>
<FormattedMessage id="customer.clear.button" />
</button>
export const mapDispatchToProps = dispatch => ({
clearUsernameForm: () => dispatch(reset(CHANGE_USERNAME_FORM)),
/**
* It requests to check if username already exists
*/
checkUsername: (value) => {
dispatch(checkSettingsUsernameAction(value, CHANGE_USERNAME_FORM, NEW_USERNAME));
},
});
My problem is that when i click the clear button my the onBlur event is firing. How to prevent this?