Created
February 5, 2018 20:11
-
-
Save Xananax/de84477004049c261d4b8c65a54e3ccf to your computer and use it in GitHub Desktop.
Basic React Input
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Tired of re-typing the same component every time | |
* This is a component that takes a value prop OR | |
* handles value as a state, internally, OR | |
* does both. | |
* | |
* It can also trigger the onChange event throttled, | |
* instead of doing so on every key stroke | |
*/ | |
import * as React from 'react' | |
import { Component } from 'react' | |
export interface Props extends React.InputHTMLAttributes<HTMLInputElement> | |
{ submit?: (value: string) => void // when pressing enter | |
; change?: (value: string) => void // when changes occur | |
; value?:string // pass this to override internal value | |
; throttle?: number // send keystrokes every <throttle> ms. Defaults to 300 | |
; handleChangeExternally?:boolean // if `true`, internal state handling is disabled. You're on your own | |
; renderer?: (props:InputRendererProps) => JSX.Element // render to any sort of markup you like | |
} | |
export interface State | |
{ value:string | |
} | |
export interface InputRendererProps | |
{ submitHandler: (evt: FormEvent<HTMLFormElement>) => any | |
, changeHandler: (evt: InputEvent<HTMLInputElement>) => any | |
, value: string | |
} | |
export const InputRenderer = | |
({ submitHandler, changeHandler, value }: InputRendererProps) => | |
( <form onSubmit={submitHandler}> | |
<input type="text" onChange={changeHandler} value={value} /> | |
</form> | |
) | |
export class Input extends Component<Props,State> | |
{ timer:number = 0 | |
; static defaultProps:Props = | |
{ throttle: 300 | |
, renderer: InputRenderer | |
} | |
; constructor(props:Props) | |
{ super(props) | |
; const value = ( typeof props.value == 'string' ? props.value+'' : '') | |
; this.state = | |
{ value | |
} | |
} | |
; submitHandler = (evt:FormEvent<HTMLFormElement>) => | |
{ evt.preventDefault() | |
; if(this.props.submit) | |
{ this.props.submit(this.state.value) | |
} | |
} | |
; changeHandler = (evt:InputEvent<HTMLInputElement>) => | |
{ evt.preventDefault() | |
; const value = evt.target.value | |
; const { change, throttle, handleChangeExternally } = this.props | |
; if( !change || !handleChangeExternally) | |
{ this.setState({value}) | |
} | |
; if( change ) | |
{ if (!handleChangeExternally && throttle ) | |
{ clearTimeout(this.timer) | |
; this.timer = setTimeout( () => change(value), throttle) | |
}else | |
{ change(value) | |
} | |
} | |
} | |
; componentWillReceiveProps(nextProps:Partial<Props>) | |
{ if(nextProps.value !== this.props.value) | |
{ const {value} = nextProps | |
; if(typeof value === 'string') | |
{ this.setState({value}) | |
} | |
} | |
} | |
; render() | |
{ const | |
{ submitHandler | |
, changeHandler | |
, props | |
, state | |
} = this | |
; const renderer = props.renderer || InputRenderer | |
; const | |
{ value } = state | |
; return React.createElement( renderer, { submitHandler, changeHandler, value }) | |
} | |
} | |
export default Input |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment