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

Commit 9c5ca43

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 8268d25 commit 9c5ca43

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
@@ -6,7 +6,7 @@ let _debugStates = []
66
let Autocomplete = React.createClass({
77

88
propTypes: {
9-
initialValue: React.PropTypes.any,
9+
value: React.PropTypes.any,
1010
onChange: React.PropTypes.func,
1111
onSelect: React.PropTypes.func,
1212
shouldItemRender: React.PropTypes.func,
@@ -17,6 +17,7 @@ let Autocomplete = React.createClass({
1717

1818
getDefaultProps () {
1919
return {
20+
value: '',
2021
inputProps: {},
2122
onChange () {},
2223
onSelect (value, item) {},
@@ -39,7 +40,6 @@ let Autocomplete = React.createClass({
3940

4041
getInitialState () {
4142
return {
42-
value: this.props.initialValue || '',
4343
isOpen: false,
4444
highlightedIndex: null,
4545
}
@@ -88,11 +88,7 @@ let Autocomplete = React.createClass({
8888

8989
handleChange (event) {
9090
this._performAutoCompleteOnKeyUp = true
91-
this.setState({
92-
value: event.target.value,
93-
}, () => {
94-
this.props.onChange(event, this.state.value)
95-
})
91+
this.props.onChange(event, event.target.value)
9692
},
9793

9894
handleKeyUp () {
@@ -146,17 +142,17 @@ let Autocomplete = React.createClass({
146142
}
147143
else {
148144
var item = this.getFilteredItems()[this.state.highlightedIndex]
145+
var value = this.props.getItemValue(item)
149146
this.setState({
150-
value: this.props.getItemValue(item),
151147
isOpen: false,
152148
highlightedIndex: null
153149
}, () => {
154150
//React.findDOMNode(this.refs.input).focus() // TODO: file issue
155151
React.findDOMNode(this.refs.input).setSelectionRange(
156-
this.state.value.length,
157-
this.state.value.length
152+
value.length,
153+
value.length
158154
)
159-
this.props.onSelect(this.state.value, item)
155+
this.props.onSelect(value, item)
160156
})
161157
}
162158
},
@@ -174,21 +170,21 @@ let Autocomplete = React.createClass({
174170

175171
if (this.props.shouldItemRender) {
176172
items = items.filter((item) => (
177-
this.props.shouldItemRender(item, this.state.value)
173+
this.props.shouldItemRender(item, this.props.value)
178174
))
179175
}
180176

181177
if (this.props.sortItems) {
182178
items.sort((a, b) => (
183-
this.props.sortItems(a, b, this.state.value)
179+
this.props.sortItems(a, b, this.props.value)
184180
))
185181
}
186182

187183
return items
188184
},
189185

190186
maybeAutoCompleteText () {
191-
if (this.state.value === '')
187+
if (this.props.value === '')
192188
return
193189
var { highlightedIndex } = this.state
194190
var items = this.getFilteredItems()
@@ -198,13 +194,13 @@ let Autocomplete = React.createClass({
198194
items[highlightedIndex] : items[0]
199195
var itemValue = this.props.getItemValue(matchedItem)
200196
var itemValueDoesMatch = (itemValue.toLowerCase().indexOf(
201-
this.state.value.toLowerCase()
197+
this.props.value.toLowerCase()
202198
) === 0)
203199
if (itemValueDoesMatch) {
204200
var node = React.findDOMNode(this.refs.input)
205201
var setSelection = () => {
206202
node.value = itemValue
207-
node.setSelectionRange(this.state.value.length, itemValue.length)
203+
node.setSelectionRange(this.props.value.length, itemValue.length)
208204
}
209205
if (highlightedIndex === null)
210206
this.setState({ highlightedIndex: 0 }, setSelection)
@@ -232,12 +228,12 @@ let Autocomplete = React.createClass({
232228
},
233229

234230
selectItemFromMouse (item) {
231+
var value = this.props.getItemValue(item);
235232
this.setState({
236-
value: this.props.getItemValue(item),
237233
isOpen: false,
238234
highlightedIndex: null
239235
}, () => {
240-
this.props.onSelect(this.state.value, item)
236+
this.props.onSelect(value, item)
241237
React.findDOMNode(this.refs.input).focus()
242238
this.setIgnoreBlur(false)
243239
})
@@ -266,7 +262,7 @@ let Autocomplete = React.createClass({
266262
top: this.state.menuTop,
267263
minWidth: this.state.menuWidth,
268264
}
269-
var menu = this.props.renderMenu(items, this.state.value, style)
265+
var menu = this.props.renderMenu(items, this.props.value, style)
270266
return React.cloneElement(menu, { ref: 'menu' })
271267
},
272268

@@ -310,7 +306,7 @@ let Autocomplete = React.createClass({
310306
onKeyDown={(event) => this.handleKeyDown(event)}
311307
onKeyUp={(event) => this.handleKeyUp(event)}
312308
onClick={this.handleInputClick}
313-
value={this.state.value}
309+
value={this.props.value}
314310
/>
315311
{this.state.isOpen && this.renderMenu()}
316312
{this.props.debug && (

0 commit comments

Comments
 (0)