问题
I've asked for more information about the error here: Should I ignore React warning: Input elements should not switch from uncontrolled to controlled?. But I'm still stuck..
So I have a case where I want to switch a time input field from holding it's own value to taking over a value from another time input field. I'm doing this using a simple 'locked' / 'unlocked' button. Clicking on that button allows me to choose whether the input field is locked (takes over value from others) or unlocked (keeps its own value).
I'm doing this inside a loop because each time field will be repeated 7 times (for each day).
Problem
However, each time I switch from regular time input field to a time input field with actions behind it, React's giving me the following error:
A component is changing an uncontrolled input of type time to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component
Explaining the code below
The part between comments goes as follow: If the locked state of the current day input field is 'true', then the input must take a value from a state and execute a onchange handler. If it is false, it shouldn't do anything and react as a basic input field.
What I have
export class OpeningHoursTable extends Component{
constructor(props) {
super(props);
this.state = {
sharedInputMo : '',
empty: undefined
};
}
render() {
const Days = [{id: 1, day: 'Monday'},{id: 2, day: 'Tuesday'},{id: 3, day: 'Wednesday'},{id: 4, day: 'Thursday'},{id: 5, day: 'Friday'},{id: 6, day: 'Saturday'},{id: 7, day: 'Sunday'}];
const Table = Days.map(({id, day}) => (
<div key={id} className='ohTableRow'>
<div className='ohTableMorning'>
<div className='ohTableContentBlock'>{day}</div>
<div className='ohTableContentBlock'>
// THIS IS THE PART THAT GIVES ME THE ERROR
<input type='time'
value={this.state['lock' + day + '_mo'] === true ? this.state.sharedInputMo || this.state.empty: this.state.empty}
onChange={this.state['lock' + day + '_mo'] === true ? thisInput => this.setState({sharedInputMo : thisInput.target.value }) : null }
/>
// THIS IS THE PART THAT GIVES ME THE ERROR
</div>
<div className='ohTableLockState' onClick={this.state['lock' + day + '_mo'] === true ? () => this.setState({ ['lock' + day + '_mo'] : false }) : () => this.setState({ ['lock' + day + '_mo'] : true }) }>
{this.state['lock' + day + '_mo'] === true ?
<Icon name='Locked' />
:
<Icon name='Unlocked' />
}
</div>
</div>
</div>
));
return (
<div className='ohTable'>
{Table}
</div>
);
}
}
回答1:
The root of your problem and the error is that you provide undefined
as a value to input and do not assign any onChange
event initially.
More specifically you pass this.state.empty
as a value, which is assigned an undefined
in the state and null
as onChange
handler.
When react gets an undefined
as a value of input and no handler, it assumes that this input is uncontrolled and all the changes will be handled by the DOM and react itself should not do anything with it.
But, later down the road, based on user action, your input gets another value this.state.sharedInputMo
and onChange
handler that turns it into controlled input. This change causes the confusion of react and gives you this warning.
回答2:
So after giving it a night's rest I solved my own problem.
This is for everyone who needs to switch between a controlled and uncontrolled object and has the same error.
Use a Switch statement to switch between a controlled and uncontrolled object. This way, React will see them both as a separate and different object; thus in front end it will seem as if you have the same object.
switch(this.state['lock' + day + '_mo']) {
case true:
return (
<div className='ohTableContentBlock'>
<input type='time' value={this.state.sharedInputMo} onChange={inputValue => this.setState({sharedInputMo2 : inputValue.target.value })} />
</div>
);
case false:
return (
<div className='ohTableContentBlock'>
<input type='time' />
</div>
);
default:
return (
<div className='ohTableContentBlock'>
<input type='time' />
</div>
);
}
来源:https://stackoverflow.com/questions/53648933/reacts-changing-controlled-to-uncontrolled-error-driving-me-crazy-what-am-i-do