I want to restore the default values on all input fields and total on the click of button 'Restore Default', but it is not working. In the code I have so far, all the elements are wrapped within a grid.
The SO questions I referred to talk about:
- Wrapping all elements in a form or a div and call reset()
- Use e.target.reset() on the event. I tried this with onClick event of button, but says that reset is not a function.
What is the preferred way to implement this functionality? Thanks in advance!
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
code1: this.props.defaults[0],
code2: this.props.defaults[1],
code3: this.props.defaults[2],
total : 0
};
this.handleInput = this.handleInput.bind(this);
this.restoreDefaults = this.restoreDefaults(this);
}
handleInput() {
//some logic
}
updateCode = (e, k) => {
this.setState({
[`code${k}`]: e.target.value
},
() => {
this.updateTotal();
});
}
updateTotal = () => {
this.setState(prevState => ({
total: (+prevState.code1 + +prevState.code2 + +prevState.code3),
}),
() => {
if (this.state.total !== 100) {
this.setState({
isTotalInvalid: true
});
} else {
this.setState({
isTotalInvalid: false
});
}
});
}
restoreDefaults() {
this.setState({
code1: this.props.defaults[0],
code2: this.props.defaults[1],
code3: this.props.defaults[2],
total: 0,
)};
}
render() {
return (
<Spacer>
<Grid>
<Grid.Row>
<Grid.Column tiny={12} medium={10}>
<input type="number" defaultValue={this.state.code1} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 1)} />
</Grid.Column>
<Grid.Column tiny={12} medium={10}>
<input type="number" defaultValue={this.state.code2} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 2)} />
</Grid.Column>
<Grid.Column tiny={12} medium={10}>
<input type="number" defaultValue={this.state.code3} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 3)} />
Total Field:
<span fontSize={14} weight={700}>{this.state.total}</span>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Button text="Restore Default" type="button" onClick=
{this.restoreDefaults} />
</Grid.Row>
</Grid>
</Spacer>
);
}
}
export default Test;
I want to restore the default values on all input fields and total on the click of button 'Restore Default', but it is not working. In the code I have so far, all the elements are wrapped within a grid.
The SO questions I referred to talk about:
- Wrapping all elements in a form or a div and call reset()
- Use e.target.reset() on the event. I tried this with onClick event of button, but says that reset is not a function.
What is the preferred way to implement this functionality? Thanks in advance!
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
code1: this.props.defaults[0],
code2: this.props.defaults[1],
code3: this.props.defaults[2],
total : 0
};
this.handleInput = this.handleInput.bind(this);
this.restoreDefaults = this.restoreDefaults(this);
}
handleInput() {
//some logic
}
updateCode = (e, k) => {
this.setState({
[`code${k}`]: e.target.value
},
() => {
this.updateTotal();
});
}
updateTotal = () => {
this.setState(prevState => ({
total: (+prevState.code1 + +prevState.code2 + +prevState.code3),
}),
() => {
if (this.state.total !== 100) {
this.setState({
isTotalInvalid: true
});
} else {
this.setState({
isTotalInvalid: false
});
}
});
}
restoreDefaults() {
this.setState({
code1: this.props.defaults[0],
code2: this.props.defaults[1],
code3: this.props.defaults[2],
total: 0,
)};
}
render() {
return (
<Spacer>
<Grid>
<Grid.Row>
<Grid.Column tiny={12} medium={10}>
<input type="number" defaultValue={this.state.code1} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 1)} />
</Grid.Column>
<Grid.Column tiny={12} medium={10}>
<input type="number" defaultValue={this.state.code2} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 2)} />
</Grid.Column>
<Grid.Column tiny={12} medium={10}>
<input type="number" defaultValue={this.state.code3} min="0" max="100" onKeyPress={this.handleInput} onBlur={e => this.updateCode(e, 3)} />
Total Field:
<span fontSize={14} weight={700}>{this.state.total}</span>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<Button text="Restore Default" type="button" onClick=
{this.restoreDefaults} />
</Grid.Row>
</Grid>
</Spacer>
);
}
}
export default Test;
Share
Improve this question
edited Mar 20, 2020 at 20:50
babybear
asked Mar 20, 2020 at 20:43
babybearbabybear
8442 gold badges11 silver badges25 bronze badges
6
- In the question you say "controlled", but these are uncontrolled. You do not assign them a value. For controlled inputs, you would just reset their values in state. – Brian Thompson Commented Mar 20, 2020 at 20:52
-
Also is there a reason why you use
onBlur
instead of just usingonChange
? – Brian Thompson Commented Mar 20, 2020 at 20:53 -
It doesn't appear that you are doing 2-way data binding. You should have a
value
attribute on your input as well that should be controlled by your state – Devon Norris Commented Mar 20, 2020 at 20:55 - 1 @DevonNorris Now that you mention value attribute, I feel that's where I'm going wrong. I'm updating states on events but not tying states to input values. – babybear Commented Mar 20, 2020 at 21:03
- 1 @Vidhi yep, try binding the values to your state and see what happens. Also here is a short article from the react docs: reactjs/docs/two-way-binding-helpers.html – Devon Norris Commented Mar 20, 2020 at 21:10
2 Answers
Reset to default 5A controlled input requires two parts.
- A
value
provided to the input - A change handler
Remember: defaultValue
only sets the input's value once. After that it has no effect.
This allows you to control the value of the inputs programatically.
I've added a very simplified example below.
In this example we control the values by keeping them in state. But this could be in props or redux or wherever.
Then when we want to reset the form, we just need to change the state back to its initial values. Since the input
is informed through the value
prop (our state) it effectively resets.
class Example extends React.Component {
state = {
code1: '',
code2: '',
code3: '',
}
handleChange = (e) => {
this.setState({ [e.target.name]: e.target.value });
}
handleReset = () => {
this.setState({
code1: '',
code2: '',
code3: '',
});
}
render() {
return (
<div>
<div>
<input
type="number"
name="code1"
value={this.state.code1}
onChange={this.handleChange}
min="0"
max="100"
/>
</div>
<div>
<input
type="number"
name="code2"
value={this.state.code2}
onChange={this.handleChange}
min="0"
max="100"
/>
</div>
<div>
<input
type="number"
name="code3"
value={this.state.code3}
onChange={this.handleChange}
min="0"
max="100"
/>
</div>
<button onClick={this.handleReset}>Reset</button>
</div>
)
}
}
ReactDOM.render(<Example/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />
To reset all the inputs with the click of a button:
- Put all the inputs in a
<form>
- Instead of
<button>
, use input reset<input type="reset" />
- Instead of
value
, set default value<input defaultValue={myDefaultValue} />
- The input reset must be within
<form>
By implementing those changes, render()
would look like this:
render() {
return (
<form>
<Spacer>
<Grid>
<Grid.Row>
<Grid.Column tiny={12} medium={10}>
<input
type="number"
defaultValue={this.state.code1}
min="0"
max="100"
onKeyPress={this.handleInput}
onBlur={e => this.updateCode(e, 1)} />
</Grid.Column>
<Grid.Column tiny={12} medium={10}>
<input
type="number"
defaultValue={this.state.code2}
min="0"
max="100"
onKeyPress={this.handleInput}
onBlur={e => this.updateCode(e, 2)} />
</Grid.Column>
<Grid.Column tiny={12} medium={10}>
<input
type="number"
defaultValue={this.state.code3}
min="0"
max="100"
onKeyPress={this.handleInput}
onBlur={e => this.updateCode(e, 3)} />
Total Field:
<span fontSize={14} weight={700}>
{this.state.total}
</span>
</Grid.Column>
</Grid.Row>
<Grid.Row>
<input
value="Restore Default"
type="reset" />
</Grid.Row>
</Grid>
</Spacer>
</form>
);
}
The <form>
element has a reset()
function that is AUTOMATICALLY called when the input reset button is clicked.
NOTE: If you add onClick
to the input reset button, the <form>
will not reset. In this case, you must manually call reset()
. So if you use onClick
like this:
<input type="reset" value="Restore Default" onClick={handleClick} />
You should manually reset the <form>
like this:
function handleClick(event) {
const form = event.currentTarget.form;
form.reset();
//YOUR CUSTOM CODE GOES HERE
}