Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
66
rated 0 times [  71] [ 5]  / answers: 1 / hits: 61088  / 8 Years ago, mon, april 18, 2016, 12:00:00

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.


More From » reactjs

 Answers
36

You need to perform a couple of steps:




  1. Your input needs to only use the value and onChange props, do not use defaultValue

  2. Initialize your state using your props to set your default value

  3. Update your state when your props change



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.


[#62514] Friday, April 15, 2016, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
angelr

Total Points: 399
Total Questions: 96
Total Answers: 101

Location: Finland
Member since Sun, May 21, 2023
1 Year ago
;