Github searching case study

  1. Case introduction

    Github searching case

    In this case, there is a search bar above and a display bar below. After searching, the user’s avatar and username will be displayed. Click on the avatar to enter the user’s homepage. Before searching, the display area should display Waiting for Search; Loading should be displayed during the search, the user avatar should be displayed when the search is successful, and the error reason should be displayed when the search fails.


  2. ideas

    In terms of subcomponents, this case should be divided into two components: the upper search component and the lower display component.

    The display of the picture and the realization of clicking the picture to enter the link: these two functions have nothing to do with JS, and should use the syntax of html, as follows

    1
    2
    3
    <a ref="userlink" href={user.html_url} target="_blank">
    <img src={user.avatar_url} alt="user_Avatar_picture" style={{ width: '100px' }} />
    </a>

  1. Implementation (using props to pass value)

    App.js components

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    export default class App extends Component {
    state = {
    users: [], //Pay attention to an empty array here, otherwise the value will be empty when there is no search, and the rendering will go wrong.
    isInitial: true,
    isLoading: false,
    err: '' //Pay attention here to initialize a null character '', in the Boolean judgment, the null character is false.
    }
    getData = (stateObj) => {
    this.setState(stateObj) //Here is to receive multiple properties of state. The parameters of the callback are all {key:value}
    } //form, so it can directly satisfy the setState syntax setState({}).
    render() {
    return (<div>
    <Search getData={this. getData} />
    <List {...this.state} /> {/*Here is to use object destructuring assignment to pass all the properties in the state, */}
    </div> ) {/*But notice that there is no XXX={}. */}
    }
    }

    Search.jsx component

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    export default class List extends Component {
    sendRequest = () => {
    this.props.getData({ isInitial: false, isLoading: true, users: [] })
    axios.get(`https://api.github.com/search/usersq=${this.input1Node.value}`
    ).then(response => {
    this.props.getData({ isLoading: false, users: response.data.items })
    }, reason => {
    this. props. getData({ isLoading: false, err: reason. message })
    }) //Note here that err can only be reason.message, not reason. Because reason is an object, an error will be reported.
    } //In addition, call getData() and add {key:value} to say that because the result is directly used for setState(), this can be written directly
    //Merge into the state, which meets the syntax requirements.
    render() {
    return (
    <div>
    <input type="text" ref={c => this.input1Node = c} />
    <button onClick={this.sendRequest}>click to search</button>
    </div>
    )
    }
    }

    List.jsx component

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    export default class List extends Component {
    render() {
    return (<div>
    {this.props.isInitial? <div>Please input text</div> : //ternary operator instead of if
    this.props.isLoading? <div>...Loading</div> :
    this.props.err? <div>{this.props.err}</div> :
    this.props.users.map((user) => {
    return <div key={user.id}>
    <div>{user.login}</div>
    <a ref="userlink" href={user.html_url} target="_blank">
    <img src={user.avatar_url} alt="avatar" style={{ width: '100px' }} />
    </a>
    </div>})
    }
    </div>)
    }
    }

  1. pay attention

    1. Use a callback function to get all the data of setState from the value passed from the child to the parent

      1
      getData = (stateObj) => {this.setState(stateObj)}
      1
      this.props.getData({ isLoading: false, users: response.data.items })

      The principle is to use the syntax of setState({key: value}) to directly wrap the value passed by the function into {key: value} format and pass it to setState(). I used setState({...stateObj}) successfully when I coded it myself before, but this is redundant code. Just like […arr], the object is unpacked and repackaged into an object.


    2. Pass props in batches, and pass the properties in the state as props, apply

      1
      <List{...this.state}/>

      Note that the normal way to pass in a single props is users={this.state.users} , and there is no user= for batch pass in.


    3. Ternary operator instead of if

      In JSX, {} can only be a statement and not if, so use the ternary operator instead. condition? a: replaces the if statement. : is equivalent to else() in the original if statement.


    4. Axios returns error.message instead of error

      If you use error, it will always report an error: Objects are not valid as a React child. This error means that in JSX {} must be string or array, but not object . The error returned by Axios is an object that cannot be rendered to the page through JSX (but can be displayed in the Console), so only error.message can be used. message Do not misspell massage.


Share