EDIT
Sorry for showing wrong use-case. All inputs inside the Form
are being passed though this.props.children
, and they can be situated at any deep point of the components tree, so the approach of passing the handleChange
directly to inputs will not work at all.
Here is code snippet with the reproduction of the problem.
class CustomSelect extends React.Component {
items = [
{ id: 1, text: "Kappa 1" },
{ id: 2, text: "Kappa 2" },
{ id: 3, text: "Kappa 3" }
]
state = {
selected: null,
}
handleSelect = (item) => {
this.setState({ selected: item })
}
render() {
var { selected } = this.state
return (
<div className="custom-select">
<input
name={this.props.name}
required
style={{ display: "none" }} // or type="hidden", whatever
value={selected
? selected.id
: ""
}
onChange={() => {}}
/>
<div>Selected: {selected ? selected.text : "nothing"}</div>
{this.items.map(item => {
return (
<button
key={item.id}
type="button"
onClick={() => this.handleSelect(item)}
>
{item.text}
</button>
)
})}
</div>
)
}
}
class Form extends React.Component {
handleChange = (event) => {
console.log("Form onChange")
}
render() {
return (
<form onChange={this.handleChange}>
{this.props.children}
</form>
)
}
}
ReactDOM.render(
<Form>
<label>This input will trigger form's onChange event</label>
<input />
<CustomSelect name="kappa" />
</Form>,
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>
As you can see, when you type something in default input (controlled or uncontrolled, whatever), form catches bubbled onChange
event. But when you are setting the value of the input programmatically (with the state
, in this case), the onChange event is not being triggered, so I cannot catch this changes inside the form's onChange
.
Is there any options to beat this problem? I tried to input.dispatchEvent(new Event("change", { bubbles: true }))
immediately after setState({ selected: input })
and inside it's callback, but there is no result.
onChange
to the form instead of the input? – CoffleForm
throughchildren
. I have edited my code snippet. Sorry for that. – Armbruster