In my React component I have a button meant to send some data over AJAX when clicked. I need to happen only the first time, i.e. to disable the button after it's first use.
How I'm trying to do this:
var UploadArea = React.createClass({
getInitialState() {
return {
showUploadButton: true
};
},
disableUploadButton(callback) {
this.setState({ showUploadButton: false }, callback);
},
// This was simpler before I started trying everything I could think of
onClickUploadFile() {
if (!this.state.showUploadButton) {
return;
}
this.disableUploadButton(function() {
$.ajax({
[...]
});
});
},
render() {
var uploadButton;
if (this.state.showUploadButton) {
uploadButton = (
<button onClick={this.onClickUploadFile}>Send</button>
);
}
return (
<div>
{uploadButton}
</div>
);
}
});
What I think happens is the state variable showUploadButton
not being updated right away, which the React docs says is expected.
How could I enforce the button to get disabled or go away all-together the instant it's being clicked?
What you could do is make the button disabled after is clicked and leave it in the page (not clickable element).
To achieve this you have to add a ref to the button element
<button ref="btn" onClick={this.onClickUploadFile}>Send</button>
and then on the onClickUploadFile function disable the button
this.refs.btn.setAttribute("disabled", "disabled");
You can then style the disabled button accordingly to give some feedback to the user with
.btn:disabled{ /* styles go here */}
If needed make sure to reenable it with
this.refs.btn.removeAttribute("disabled");
Update: the preferred way of handling refs in React is with a function and not a string.
<button
ref={btn => { this.btn = btn; }}
onClick={this.onClickUploadFile}
>Send</button>
this.btn.setAttribute("disabled", "disabled");
this.btn.removeAttribute("disabled");
here is a small example using the code you provided https://jsfiddle.net/69z2wepo/30824/
The solution is to check the state immediately upon entry to the handler. React guarantees that setState inside interactive events (such as click) is flushed at browser event boundary. Ref: https://github.com/facebook/react/issues/11171#issuecomment-357945371
// In constructor
this.state = {
disabled : false
};
// Handler for on click
handleClick = (event) => {
if (this.state.disabled) {
return;
}
this.setState({disabled: true});
// Send
}
// In render
<button onClick={this.handleClick} disabled={this.state.disabled} ...>
{this.state.disabled ? 'Sending...' : 'Send'}
<button>
Tested as working one: http://codepen.io/zvona/pen/KVbVPQ
class UploadArea extends React.Component {
constructor(props) {
super(props)
this.state = {
isButtonDisabled: false
}
}
uploadFile() {
// first set the isButtonDisabled to true
this.setState({
isButtonDisabled: true
});
// then do your thing
}
render() {
return (
<button
type='submit'
onClick={() => this.uploadFile()}
disabled={this.state.isButtonDisabled}>
Upload
</button>
)
}
}
ReactDOM.render(<UploadArea />, document.body);
You can try using React Hooks to set the Component State.
import React, { useState } from 'react';
const Button = () => {
const [double, setDouble] = useState(false);
return (
<button
disabled={double}
onClick={() => {
// doSomething();
setDouble(true);
}}
/>
);
};
export default Button;
Make sure you are using ^16.7.0-alpha.x
version of react
and react-dom
.
Hope this helps you!
If you want, just prevent to submit.
How about using lodash.js debounce
Grouping a sudden burst of events (like keystrokes) into a single one.
https://lodash.com/docs/4.17.11#debounce
<Button accessible={true}
onPress={_.debounce(async () => {
await this.props._selectUserTickets(this.props._accountId)
}, 1000)}
></Button>
来源:https://stackoverflow.com/questions/35315872/reactjs-prevent-multiple-times-button-press