Case introduction
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.
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>
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
17export 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
20export 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
17export 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>)
}
}
pay attention
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 tosetState()
. I usedsetState({...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.
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 nouser=
for batch pass in.
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 toelse()
in the original if statement.
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.