-
-
Save krambertech/76afec49d7508e89e028fce14894724c to your computer and use it in GitHub Desktop.
import React, { Component } from 'react'; | |
import TextField from 'components/base/TextField'; | |
const WAIT_INTERVAL = 1000; | |
const ENTER_KEY = 13; | |
export default class TextSearch extends Component { | |
constructor(props) { | |
super(); | |
this.state = { | |
value: props.value | |
}; | |
} | |
componentWillMount() { | |
this.timer = null; | |
} | |
handleChange(value) { | |
clearTimeout(this.timer); | |
this.setState({ value }); | |
this.timer = setTimeout(::this.triggerChange, WAIT_INTERVAL); | |
} | |
handleKeyDown(e) { | |
if (e.keyCode === ENTER_KEY) { | |
::this.triggerChange(); | |
} | |
} | |
triggerChange() { | |
const { value } = this.state; | |
this.props.onChange(value); | |
} | |
render() { | |
const { className } = this.props; | |
return ( | |
<TextField | |
className={className} | |
placeholder={l('Search')} | |
value={this.state.value} | |
onChange={::this.handleChange} | |
onKeyDown={::this.handleKeyDown} | |
/> | |
); | |
} | |
} |
👍
That's really useful and exactly what i was looking for. Thanks !
👍
Sorry for the ignorance.
Can you please explain what ::
before your function stands for?
@noushad-pp
It's an ECMAScript function bind syntax as proposed here
Minor note on using that ::
bind syntax: Will take a slight performance hit as the function will need to be bound on every render. At least this is my understanding. To avoid this, binding should occur in the constructor.
Thanks! Really helpful!
well done
Thank you
But I have modified some code. It works with my project.
import React, { Component } from 'react'
const WAIT_INTERVAL = 1000
const ENTER_KEY = 13
class TextSearch extends Component {
state = {
value: ''
}
timer = null
handleChange = e => {
clearTimeout(this.timer)
this.setState({ value: e.target.value })
this.timer = setTimeout(this.triggerChange, WAIT_INTERVAL)
}
handleKeyDown = e => {
if (e.keyCode === ENTER_KEY) {
clearTimeout(this.timer)
this.triggerChange()
}
}
triggerChange = () => {
const { value } = this.state
this.props.onChange(value)
}
render() {
const { ...rest } = this.props
return (
<input
type={rest.type}
className={rest.className}
placeholder={rest.placeholder}
value={this.state.value}
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
/>
)
}
}
export default TextSearch
👍
@obbaeiei, you should clear timeout inside handleKeyDown
too. If your triggerChange
will do fetch to backend (via action creator if u use redux), you will see two requests after Enter pressed.
@0t3dWCE
I see. Thank you.
Thank you its work fine for me too
Any way to do this without this.setState({ value });
?
Because in reality a change is made in the local state immediately and then a props is dispatched to the parent component.
couldn't thank you enough for this, however I was wondering if there is any better way of doing the same.
Thank you
But I have modified some code. It works with my project.
import React, { Component } from 'react' const WAIT_INTERVAL = 1000 const ENTER_KEY = 13 class TextSearch extends Component { state = { value: '' } timer = null handleChange = e => { clearTimeout(this.timer) this.setState({ value: e.target.value }) this.timer = setTimeout(this.triggerChange, WAIT_INTERVAL) } handleKeyDown = e => { if (e.keyCode === ENTER_KEY) { clearTimeout(this.timer) this.triggerChange() } } triggerChange = () => { const { value } = this.state this.props.onChange(value) } render() { const { ...rest } = this.props return ( <input type={rest.type} className={rest.className} placeholder={rest.placeholder} value={this.state.value} onChange={this.handleChange} onKeyDown={this.handleKeyDown} /> ) } } export default TextSearch
Hey, can you explain what is type= rest.type attribute in input element.
Thank you
But I have modified some code. It works with my project.import React, { Component } from 'react' const WAIT_INTERVAL = 1000 const ENTER_KEY = 13 class TextSearch extends Component { state = { value: '' } timer = null handleChange = e => { clearTimeout(this.timer) this.setState({ value: e.target.value }) this.timer = setTimeout(this.triggerChange, WAIT_INTERVAL) } handleKeyDown = e => { if (e.keyCode === ENTER_KEY) { clearTimeout(this.timer) this.triggerChange() } } triggerChange = () => { const { value } = this.state this.props.onChange(value) } render() { const { ...rest } = this.props return ( <input type={rest.type} className={rest.className} placeholder={rest.placeholder} value={this.state.value} onChange={this.handleChange} onKeyDown={this.handleKeyDown} /> ) } } export default TextSearchHey, can you explain what is type= rest.type attribute in input element.
Never mind, got it, its the rest/spread thing you are using to pass the props passed to the component.
Thanks again.
Thank you
But I have modified some code. It works with my project.
import React, { Component } from 'react' const WAIT_INTERVAL = 1000 const ENTER_KEY = 13 class TextSearch extends Component { state = { value: '' } timer = null handleChange = e => { clearTimeout(this.timer) this.setState({ value: e.target.value }) this.timer = setTimeout(this.triggerChange, WAIT_INTERVAL) } handleKeyDown = e => { if (e.keyCode === ENTER_KEY) { clearTimeout(this.timer) this.triggerChange() } } triggerChange = () => { const { value } = this.state this.props.onChange(value) } render() { const { ...rest } = this.props return ( <input type={rest.type} className={rest.className} placeholder={rest.placeholder} value={this.state.value} onChange={this.handleChange} onKeyDown={this.handleKeyDown} /> ) } } export default TextSearch
Thanks
👍
Initialise
this.timer in constructor instead of lifecycle
constructor( ) {
super()
this.timer = null
}
I am trying to make an API call. But, as soon as I am writing some in the textbox. I am getting "Uncaught TypeError: this.props.onChange is not a function at TextSearch.triggerChange ". Thanks.
Would be great if someone will put the same example but with react hook (for react component) example.
Hi
For react hook I found this great article :
Frédérik
👍
Great share ! Thank you 👍
I did the update told by @barsbek and also added a "searchChanged" boolean so there's no useless API call if the user frantically taps Enter.
handleChange(e) {
clearTimeout(this.timerId);
this.setState({ search: e.target.defaultValue });
this.searchChanged = true;
this.timerId = setTimeout(this.updateList, SearchFolder.WAIT_INTERVAL);
}
handleKeyDown(e) {
if (e.keyCode === SearchFolder.ENTER_KEY && this.searchChanged) {
clearTimeout(this.timerId);
this.updateList();
}
}
updateList() {
this.searchChanged = false;
this.repository.peek(this.state.search, 0, 15, 0).then((response: FolderListItem[]) => {
this.setState({ listItems: response });
}).catch((error) => {
this.setState({ item: "Erreur : " + error.message });
});
}
This is exactly what I'm looking for! Much appreciated 👍