Search.js
1 import React, { Component } from 'react'; 2 import { withRouter } from 'react-router-dom'; 3 import { FormGroup, InputGroup, FormControl, Button, Glyphicon } from 'react-bootstrap'; 4 5 /** 6 * Class that renders a form to faciliate searching of 7 * for a username and to redirect to that user's tweets 8 * page. 9 * 10 * @extends React.Component 11 */ 12 class Search extends Component { 13 14 //#region Constructor 15 constructor(props, context) { 16 super(props, context); 17 18 // initial state 19 this.state = { 20 username: '', 21 usernameHasChanged: false 22 }; 23 } 24 //#endregion 25 26 //#region Component events 27 /** 28 * Handles the 'Search' button click event which 29 * sends the browser to the route to see the specified 30 * user's tweets. 31 * 32 * @returns {null} 33 */ 34 _handleClick(e) { 35 // if the form is in error, or the user has not typed in a username, do no nothing 36 if (this._getValidationState() === 'error' || !this.state.usernameHasChanged) { 37 return e.preventDefault(); 38 } 39 40 // redirec the user to the user's tweets page 41 this.props.history.push('/@' + this.state.username); 42 } 43 44 /** 45 * When user changes an input value, record that in the state. 46 * 47 * @param {SyntheticEvent} cross-browser wrapper around the browser’s native event 48 * 49 * @return {null} 50 */ 51 _handleChange(e) { 52 let state = { usernameHasChanged: true }; 53 state[e.target.name] = e.target.value; 54 this.setState(state); 55 } 56 //#endregion 57 58 //#region Helper methods 59 /** 60 * Validates the form. Return null for no state change, 61 * 'success' if valid. 62 * 63 * @return {string} null for no state change, 'success' 64 * if valid. 65 */ 66 _getValidationState() { 67 68 // ensure that the username has been changed and that a user has typed something in 69 return (this.state.username === '' && !this.state.usernameHasChanged) || this.state.username.length > 0 ? null : 'error'; 70 } 71 //#endregion 72 73 //#region React lifecycle events 74 render() { 75 let validationState = this._getValidationState(); 76 let isValid = validationState !== 'error'; 77 78 return ( 79 <FormGroup validationState={validationState}> 80 <InputGroup> 81 <FormControl 82 type="text" 83 value={this.state.username} 84 placeholder="username" 85 name="username" 86 onChange={ (e) => this._handleChange(e) } 87 onKeyPress={ (e) => e.key === 'Enter' ? this._handleClick(e) : false } 88 /> 89 <InputGroup.Button> 90 <Button 91 bsStyle="primary" 92 disabled={ !isValid } 93 onClick={ !isValid ? null : (e) => this._handleClick(e) }><Glyphicon glyph="search" /></Button> 94 </InputGroup.Button> 95 </InputGroup> 96 </FormGroup> 97 ); 98 } 99 //#endregion 100 } 101 102 export default withRouter(Search);