Skip to main content
Version: 3.x

Lifecycle & State

In this section, we will learn how to reuse and encapsulate a Clock component. It will set the timer, and updated once per second.

We can start over encapsulating the clock:

class Clock extends Component {
render () {
return (
<View>
<Text>Hello, world!</Text>
<Text>And the time is {this.state.date.toLocaleTimeString()}.</Text>
</View>
)
}
}

Clock is defined as a class, now use will allow us to use other features, the local and life cycle such as hook.

For a class to add local state

First, we need to add a class constructors to initialize the state this.state:

class Clock extends Component {
constructor (props) {
super(props)
this.state = { date: new Date() }
}

render () {
return (
<View>
<Text>Hello, world!</Text>
<Text>And the time is {this.state.date.toLocaleTimeString()}.</Text>
</View>
)
}
}

Notice how we deliver props to the base constructor:

constructor (props) {
super(props)
this.state = { date: new Date() }
}

Class constructor component should always use props call basis. Next, we will make the Clock to set their own timer and updated once per second.

The method of life cycle are added to the class

In application, with many components in the destruction of release resources component occupies very important.

Whenever Clock components loaded into the DOM in first time, we all want to generate timer, it is called mount in Taro/React.

Also, when there is a Clock generated by the DOM has been removed, we will also want to clear the timer, this is known as unloading in Taro/React.

We can be declared in the component class special method, when the component mounted or uninstall, to run some code:

class Clock extends Component {
constructor (props) {
super(props)
this.state = { date: new Date() }
}

componentDidMount() {

}

componentWillUnmount() {

}

render () {
return (
<View>
<Text>Hello, world!</Text>
<Text>And the time is {this.state.date.toLocaleTimeString()}.</Text>
</View>
)
}
}

These methods is called the life cycle of hooks.

When the component output to the DOM after executes componentDidMount() hooks, it is a good place to set up the timer:

componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
)
}

Notice how we save the timer in this ID.

Although this.props set by Taro itself and this.state has special meaning, but if you need to store is not used for visual output, you can add other fields hand movements in the class.

If you're not render() used in something, it should not be in the state.

We will be in componentWillUnmount() uninstall timer in () hook life cycle:

componentWillUnmount () {
clearInterval(this.timerID)
}

Finally, we implement the execute every second tick() method.

It will use this.setState() to update the local state:

import Taro, { Component } from '@tarojs/taro'

class Clock extends Component {
constructor (props) {
super(props)
this.state = { date: new Date() }
}

componentDidMount () {
this.timerID = setInterval(
() => this.tick(),
1000
);
}

componentWillUnmount () {
clearInterval(this.timerID)
}

tick () {
this.setState({
date: new Date()
});
}

render() {
return (
<View>
<Text>Hello, world!</Text>
<Text>And the time is {this.state.date.toLocaleTimeString()}.</Text>
</View>
)
}
}

Proper use of the State

About the setState () there are three things need to know:

Do not directly update the status

For example, this code not to render the component:

// Wrong
this.state.comment = 'Hello'

Should be used setState():

// Correct
this.setState({ comment: 'Hello' })

setState() function is the only can update this.state place.

Status updates must be asynchronous

Taro can be multiple setState() call merged into a single call to improve performance.

Because this.state and props must be asynchronous update, so you can't in setState immediately get state values, such as:

// Suppose we set this.state.counter = 0
updateCounter () {
this.setState({
counter: 1
})
console.log(this.state.counter) // This counter is 0
}

Is the right thing in this way, the setState second parameter pass in a callback:

// Suppose we set this.state.counter = 0
updateCounter () {
this.setState({
counter: 1
}, () => {
// In this function you can get after setState values
})
}

This is the Taro and React a different places: Doesn't always React the setState asynchronous, a set of transaction mechanism, his inner control, and React the implementation of the 15/16 also each are not identical. For Taro, setState after you provide will be joining an array, and then the execution of the next one eventloop merge them.

state update will be merged

When you call setState(), Taro will combine the current state of the object to you provide.

For example, your state may contain several independent variables:

constructor(props) {
super(props)
this.state = {
posts: [],
comments: []
}
}

And then through a call to independence setState() call to update them respectively:

componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});

fetchComments().then(response => {
this.setState({
comments: response.comments
})
})
}

The merger is shallow, so this.setState({comments}) will not change this.state.posts value, but will completely replace this.state.comments value.