Introduction

在這個範例中,我們從 App 點擊傳入 prop 給 LikeButton->props->id, 在 LikeButton 設定點擊事件修改 LikeButton->state->liked,後面會介紹這些內容是怎麼組成的。

程式碼放在:github

App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var React = require('react');
var LikeButton = require('./LikeButton.js');

var App = React.createClass({
getInitialState() {
return { id: 1 };
},

handleClick(e) {
this.setState({ id: this.state.id+1 });
},

render() {
return (
<div>
<div>React Example</div>
<LikeButton id={this.state.id}/>
<p onClick={this.handleClick.bind(this)}>
點擊修改 this.state.id,透過 LikeButton id 傳入
</p>
</div>
);
}
});

React.render(<App />, document.body);
LikeButton.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var React = require('react');

var LikeButton = React.createClass({
getInitialState() {
return { liked: false };
},

getDefaultProps (){
return { id: 1 };
},

handleClick(e) {
this.setState({ liked: !this.state.liked });
},

render() {
return (
<div>
<p onClick={this.handleClick.bind(this)}>
'this.state.like =>' {this.state.liked? 'true' : 'false'}
<br />
點擊修改 this.state.lik
</p>
<p>
'this.prop.id =>' {this.props.id}
<br />
透過上層點擊修改傳入之 this.props.id
</p>
</div>
);
},
});

module.exports = LikeButton;

Props & State

  • state

state 是 Component 的當前狀態,可以想像成是 “State Machine”,我們可以根據狀態 state 去改變不同的 UI。一旦 state 更改,Component 會呼叫 render 重新渲染 UI。

1
2
3
getInitialState() {
return { key: value };
}

可以利用以下兩個函數進行更改:

* setState(object nextState[, function callback])
* replaceState(object nextState[, function callback])
  • props

props 就是 Component 的屬性,必須由外部傳入,this.props 是不可更改的。

1
2
3
getDefaultProps (){
return { key: value };
}

可以由呼叫 Component 的地方傳入參數:

* <Component id={this.state.id}/>

Event Handle

事件呼叫要注意的是需要加上 bind() 綁定物件。

1
2
3
4
5
6
7
8
9
10
11
12
handleClick(e) {
this.setState({ key: newValue });
},
render() {
return (
<div>
<p onClick={this.handleClick.bind(this)}>
Click to toggle by this.
</p>
</div>
);
}

Lifecycle

此外, react 有提供一些函數,可以依照需求在不同的時間點自動觸發。

  • componentWillMount(): 渲染前調用一次,這個時候DOM結構還沒有渲染。
  • componentDidMount(): 渲染完成後調用一次,這個時候DOM結構已經渲染了。
  • shouldComponentUpdate(): 接收到新的props或state時調用。
  • componentWillReceiveProps(): 在接收到新的props時,會調用這個方法。
  • componentWillUpdate(): 更新前調用。
  • componentDidUpdate(): 更新後調用。
  • componentWillUnmount(): 組件移除前調用。

React on ES6+

以下紀錄一些改用 ES6+ 的寫法:

Classes

1
2
3
4
5
6
7
8
9
10
11
12
13
// The ES5 way
var Photo = React.createClass({
componentWillMount: function() { … },
render: function() { … },
});
// The ES6+ way
class Photo extends React.Component {
constructor(props) {
super(props);
// Operations usually carried out in componentWillMount go here
}
render() { … }
}

Property initializers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// The ES5 way
var Video = React.createClass({
getDefaultProps: function() {
return {
autoPlay: false,
maxLoops: 10,
};
},
getInitialState: function() {
return {
loopsRemaining: this.props.maxLoops,
};
},
propTypes: {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
},
});
// The ES6+ way
class Video extends React.Component {
static defaultProps = {
autoPlay: false,
maxLoops: 10,
}
static propTypes = {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
}
state = {
loopsRemaining: this.props.maxLoops,
}
}

Arrow functions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// The ES5 way
// Autobinding, brought to you by React.createClass
var PostInfo = React.createClass({
handleOptionsButtonClick: function(e) {
// Here, 'this' refers to the component instance.
this.setState({showOptionsModal: true});
},
});
// The ES6+ way
// Manually bind this method to the component instance...
class PostInfo extends React.Component {
constructor(props) {
super(props);
this.handleOptionsButtonClick = this.handleOptionsButtonClick.bind(this);
}
handleOptionsButtonClick(e) {
// ...to ensure that 'this' refers to the component instance here.
this.setState({showOptionsModal: true});
}
}

Reference

[1] React 组件
[2] Component Specs and Lifecycle
[3] React Component Lifecycle
[4] React:组件的生命周期
[5] Reactjs 的 lifecycle
[6] 5 Practical Examples For Learning The React Framework
[7] React on ES6+
[8] 用 ES6 寫 React Component


License


本著作由 Chang, Wei-Yaun (v123582) 製作,
創用CC 姓名標示-相同方式分享 3.0 Unported授權條款釋出。