Edit: I don't want to call handleChange only if the button has been clicked. It has nothing to do with handleClick. I gave an example in the @shubhakhatri answer's comment.
I want to change the input value according to state, the value is changing but it doesn't trigger handleChange()
method. How can I trigger handleChange()
method ?
class App extends React.Component { constructor(props) { super(props) this.state = { value: 'random text' } } handleChange (e) { console.log('handle change called') } handleClick () { this.setState({value: 'another random text'}) } render () { return ( <div> <input value={this.state.value} onChange={this.handleChange}/> <button onClick={this.handleClick.bind(this)}>Change Input</button> </div> ) } } ReactDOM.render(<App />, document.getElementById('app'))
Here is the codepen link: http://codepen.io/madhurgarg71/pen/qrbLjp
State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.
To get the value of an input on change in React, set an onChange event handler on the input, then use the target. value property of the Event object passed to the handler to get the input value. The message is updated when the input value changes.
You need to trigger the onChange
event manually. On text inputs onChange listens for input
events.
So in you handleClick
function you need to trigger event like
handleClick () { this.setState({value: 'another random text'}) var event = new Event('input', { bubbles: true }); this.myinput.dispatchEvent(event); }
Complete code
class App extends React.Component { constructor(props) { super(props) this.state = { value: 'random text' } } handleChange (e) { console.log('handle change called') } handleClick () { this.setState({value: 'another random text'}) var event = new Event('input', { bubbles: true }); this.myinput.dispatchEvent(event); } render () { return ( <div> <input readOnly value={this.state.value} onChange={(e) => {this.handleChange(e)}} ref={(input)=> this.myinput = input}/> <button onClick={this.handleClick.bind(this)}>Change Input</button> </div> ) } } ReactDOM.render(<App />, document.getElementById('app'))
Codepen
Edit: As Suggested by @Samuel in the comments, a simpler way would be to call handleChange
from handleClick
if you don't need to the event object
in handleChange
like
handleClick () { this.setState({value: 'another random text'}) this.handleChange(); }
I hope this is what you need and it helps you.
I tried the other solutions and nothing worked. This is because of input logic in React.js has been changed. For detail, you can see this link: https://hustle.bizongo.in/simulate-react-on-change-on-controlled-components-baa336920e04.
In short, when we change the value of input by changing state and then dispatch a change event then React will register both the setState and the event and consider it a duplicate event and swallow it.
The solution is to call native value setter on input (See setNativeValue function in following code)
Example Code
import React, { Component } from 'react' export class CustomInput extends Component { inputElement = null; // THIS FUNCTION CALLS NATIVE VALUE SETTER setNativeValue(element, value) { const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set; const prototype = Object.getPrototypeOf(element); const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set; if (valueSetter && valueSetter !== prototypeValueSetter) { prototypeValueSetter.call(element, value); } else { valueSetter.call(element, value); } } constructor(props) { super(props); this.state = { inputValue: this.props.value, }; } addToInput = (valueToAdd) => { this.setNativeValue(this.inputElement, +this.state.inputValue + +valueToAdd); this.inputElement.dispatchEvent(new Event('input', { bubbles: true })); }; handleChange = e => { console.log(e); this.setState({ inputValue: e.target.value }); this.props.onChange(e); }; render() { return ( <div> <button type="button" onClick={() => this.addToInput(-1)}>-</button> <input readOnly ref={input => { this.inputElement = input }} name={this.props.name} value={this.state.inputValue} onChange={this.handleChange}></input> <button type="button" onClick={() => this.addToInput(+1)}>+</button> </div> ) } } export default CustomInput
Result
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With