I have the following code in my component. It will get called when I update certain things, thereby replacing a bunch of things in the UI. Everything is updating EXCEPT the value of the input as seen by the user.
let input = {
id: 'discount-' + geo + '-' + segment,
value: percentage,
disabled: applyToAll,
placeholder: '0.00'
};
cells.push(
<td key={'cell-' + geo + '-' + segment} className="discount-segment cfix">
<Text {...input} />
</td>
);
This is what <Text>
returns, with things removed for clarity
return (
<div className={containerClasses.join(' ')} id={'field-container-' + id}>
{label}
<input
autoComplete="off"
type="text"
id={id}
ref="input"
{...extraProps}
name={id}
className={classes.join(' ')}
defaultValue={this.props.value}
onChange={this.props.onChange}
/>
</div>
);
Everything renders fine. Let's say the percentage
value is 5
on start, it will show 5
in the field. I then do something else that updates percentage
to 50. (A console log will show the right number on re-render). However the value is only showing 5
in the UI still. I am using defaultValue
on the input field, but I figure that should be changing as the whole thing re-renders from parent.
Edit
Updated <Text>
to set value
instead of defaultValue
. However then I need to use state
to update the value when user types. Then when I re-render, I'm sending in new props with proper value, but of course props isn't updated. Catch-22 for me.
You need to perform a couple of steps:
value
and onChange
props, do not use defaultValue
So, for example:
const MyComponent = React.createClass({
propTypes: {
defaultInputValue: React.PropTypes.string
},
getInitialState() {
return {
inputValue: this.props.defaultInputValue
};
},
componentWillReceiveProps(nextProps) {
if (nextProps.defaultInputValue !== this.props.inputValue) {
//Forcibly overwrite input value to new default if the default ever changes
this.setState({inputValue: nextProps.defaultInputValue});
}
},
render() {
return <input type="text"
value={this.state.inputValue}
onChange={e => this.setState({inputValue: e.target.value})} />;
}
});
In general initializing state off of props is a no-no. I would probably cringe a little bit if I saw this come across in a code review as there is probably some behavior that can be simplified.
You can also do:
<input value={this.state.inputValue || this.props.defaultInputValue} />
Such that the value of the input reverts to the prop value if you ever clear out the input. In this case you wouldn't have to forcibly overwrite the state with the new props.
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