Skip to content
This repository was archived by the owner on Jul 19, 2019. It is now read-only.

Commit c98f038

Browse files
committed
[changed] Stop holding input value in state
a.k.a. replace `props.initialValue` with `props.value`. This change makes the behaviour of Autocomplete closer to that of native input elements, i.e. you are forced to always supply the current value which the input should display, and the element will provide the updated value via the `onChange` callback (and `onSelect`). Upgrade path: Before: ```js class MyWidget extends Component { render() { return ( <Autocomplete initialValue="hello" /> ) } } ``` After: ```js class MyWidget extends Component { constructor() { this.state = { value: 'hello' } } render() { return ( <Autocomplete value={this.state.value} onChange={event => this.setState({ value: event.target.value })} onSelect={value => this.setState({ value })} /> ) } } ``` This is obviously a breaking change. Closes #49
1 parent 9078d54 commit c98f038

File tree

1 file changed

+16
-20
lines changed

1 file changed

+16
-20
lines changed

lib/Autocomplete.js

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ let _debugStates = []
77
let Autocomplete = React.createClass({
88

99
propTypes: {
10-
initialValue: React.PropTypes.any,
10+
value: React.PropTypes.any,
1111
onChange: React.PropTypes.func,
1212
onSelect: React.PropTypes.func,
1313
shouldItemRender: React.PropTypes.func,
@@ -19,6 +19,7 @@ let Autocomplete = React.createClass({
1919

2020
getDefaultProps () {
2121
return {
22+
value: '',
2223
inputProps: {},
2324
labelText: '',
2425
onChange () {},
@@ -42,7 +43,6 @@ let Autocomplete = React.createClass({
4243

4344
getInitialState () {
4445
return {
45-
value: this.props.initialValue || '',
4646
isOpen: false,
4747
highlightedIndex: null,
4848
}
@@ -92,11 +92,7 @@ let Autocomplete = React.createClass({
9292

9393
handleChange (event) {
9494
this._performAutoCompleteOnKeyUp = true
95-
this.setState({
96-
value: event.target.value,
97-
}, () => {
98-
this.props.onChange(event, this.state.value)
99-
})
95+
this.props.onChange(event, event.target.value)
10096
},
10197

10298
handleKeyUp () {
@@ -151,17 +147,17 @@ let Autocomplete = React.createClass({
151147
else {
152148
// text entered + menu item has been highlighted + enter is hit -> update value to that of selected menu item, close the menu
153149
var item = this.getFilteredItems()[this.state.highlightedIndex]
150+
var value = this.props.getItemValue(item)
154151
this.setState({
155-
value: this.props.getItemValue(item),
156152
isOpen: false,
157153
highlightedIndex: null
158154
}, () => {
159155
//this.refs.input.focus() // TODO: file issue
160156
this.refs.input.setSelectionRange(
161-
this.state.value.length,
162-
this.state.value.length
157+
value.length,
158+
value.length
163159
)
164-
this.props.onSelect(this.state.value, item)
160+
this.props.onSelect(value, item)
165161
})
166162
}
167163
},
@@ -179,21 +175,21 @@ let Autocomplete = React.createClass({
179175

180176
if (this.props.shouldItemRender) {
181177
items = items.filter((item) => (
182-
this.props.shouldItemRender(item, this.state.value)
178+
this.props.shouldItemRender(item, this.props.value)
183179
))
184180
}
185181

186182
if (this.props.sortItems) {
187183
items.sort((a, b) => (
188-
this.props.sortItems(a, b, this.state.value)
184+
this.props.sortItems(a, b, this.props.value)
189185
))
190186
}
191187

192188
return items
193189
},
194190

195191
maybeAutoCompleteText () {
196-
if (this.state.value === '')
192+
if (this.props.value === '')
197193
return
198194
var { highlightedIndex } = this.state
199195
var items = this.getFilteredItems()
@@ -203,13 +199,13 @@ let Autocomplete = React.createClass({
203199
items[highlightedIndex] : items[0]
204200
var itemValue = this.props.getItemValue(matchedItem)
205201
var itemValueDoesMatch = (itemValue.toLowerCase().indexOf(
206-
this.state.value.toLowerCase()
202+
this.props.value.toLowerCase()
207203
) === 0)
208204
if (itemValueDoesMatch) {
209205
var node = this.refs.input
210206
var setSelection = () => {
211207
node.value = itemValue
212-
node.setSelectionRange(this.state.value.length, itemValue.length)
208+
node.setSelectionRange(this.props.value.length, itemValue.length)
213209
}
214210
if (highlightedIndex === null)
215211
this.setState({ highlightedIndex: 0 }, setSelection)
@@ -237,12 +233,12 @@ let Autocomplete = React.createClass({
237233
},
238234

239235
selectItemFromMouse (item) {
236+
var value = this.props.getItemValue(item);
240237
this.setState({
241-
value: this.props.getItemValue(item),
242238
isOpen: false,
243239
highlightedIndex: null
244240
}, () => {
245-
this.props.onSelect(this.state.value, item)
241+
this.props.onSelect(value, item)
246242
this.refs.input.focus()
247243
this.setIgnoreBlur(false)
248244
})
@@ -271,7 +267,7 @@ let Autocomplete = React.createClass({
271267
top: this.state.menuTop,
272268
minWidth: this.state.menuWidth,
273269
}
274-
var menu = this.props.renderMenu(items, this.state.value, style)
270+
var menu = this.props.renderMenu(items, this.props.value, style)
275271
return React.cloneElement(menu, { ref: 'menu' })
276272
},
277273

@@ -318,7 +314,7 @@ let Autocomplete = React.createClass({
318314
onKeyDown={(event) => this.handleKeyDown(event)}
319315
onKeyUp={(event) => this.handleKeyUp(event)}
320316
onClick={this.handleInputClick}
321-
value={this.state.value}
317+
value={this.props.value}
322318
id={this.id}
323319
/>
324320
{this.state.isOpen && this.renderMenu()}

0 commit comments

Comments
 (0)