FE 讀書會(4-2):React Props and State
Props
就是
組件屬性
,在初始設定,建立後不變動
回想一下 React Element
React.createElement(type
, [props]
, [...children]
)
我們用 code 來看一下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>My Component</title>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script>
//設計組件類別
class MyHead extends React.Component
{
render(){
return React.createElement("H" + this.props.level, null, "Hello World");
}
}
window.addEventListener("load", ()=>{
//1. 建立自訂的React組件實體
let myHead = React.createElement(MyHead, {level:1});
//2. 將建立好的React組件實體畫到容器中
ReactDOM.render(myHead, document.body);
})
</script>
</head>
</html>
在
React.createElement
的第二個參數我們傳入{level:1}
的物件,然後在class
中使用this.props
取得外部傳入的屬性(也就是this.props.level
)
使用 Props
來實作巢狀結構
回到剛剛的定義
React.createElement(type
, [props]
, [...children]
)
第三個參數是 子元件
想像我們要製作一個如下圖一樣的架構,我們會需要 MyHeadList
以及 MyHead
兩種 class:
我們直接看 code
class MyHead extends React.Component
{
render(){
return React.createElement("H" + this.props.level, null, "Hello World");
}
}
class MyHeadList extends React.Component{
render(){
let heads = [];
let head;
for(let i = 0; i<6;i++){
head = React.createElement(MyHead, {level:(i + 1)});
heads.push(head);
}
return React.createElement("div", null, heads);
}
}
放到剛剛的 Sample 後變成:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>My Component</title>
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script>
//設計組件類別
class MyHead extends React.Component
{
render(){
return React.createElement("H" + this.props.level, null, "Hello World");
}
}
class MyHeadList extends React.Component{
render(){
let heads = [];
let head;
for(let i = 0; i<6;i++){
head = React.createElement(MyHead, {level:(i + 1)});
heads.push(head);
}
return React.createElement("div", null, heads);
}
}
window.addEventListener("load", ()=>{
//1. 建立自訂的React組件實體
let myHeadList = React.createElement(MyHeadList, null);
//2. 將建立好的React組件實體畫到容器中
ReactDOM.render(myHeadList, document.body);
})
</script>
</head>
</html>
如果用 F12
打開 Chrome 的 DevTools,會看到其實上面的 code 跑出:
<body>
<div>
<h1>Hello World</h1>
<h2>Hello World</h2>
<h3>Hello World</h3>
<h4>Hello World</h4>
<h5>Hello World</h5>
</div>
</body>
State
就是
組件狀態
,預期未來會變動的設定
先回過頭看一下剛剛省略的 React component constructor
在寫
constructor
的時候,必定要有一個props
的參數, 參數必須傳遞給母元件
constructor(props){
super(props);
}
接著看看 State
的 code
class MyHeadList extends React.Component{
constructor(props){
super(props);
this.state={maxLevel:3};
window.setTimeout(()=>{
//this.setState({maxLevel:6});
this.setState((currentState, currentProps)=>({maxLevel: currentState.maxLevel + 1}));
}, 2000);
}
render(){
let heads = [];
let head;
for(let i = 0; i<this.state.maxLevel;i++){
head = React.createElement(MyHead, {level:(i + 1)});
heads.push(head);
}
return React.createElement("div", null, heads);
}
}
在預設的狀態下, this.state
為空白物件
在這個範例中
我們在 constructor
中指派物件 {maxLevel:3}
給 this.state
由於 State
的定義中有說 *預期未來會變動的設定*,我們也要知道如變動 this.state
使 state
變動時,我們會使用 setState
的 method 變動 state
** 且記,變動不可以直接用 this.state=newState
,否則有可能導致狀態樹的錯亂問題…
setState
可以直接傳入新的物件,
this.setState({maxLevel:6});
或是使用函式
this.setState((currentState, currentProps)=>({maxLevel: currentState.maxLevel + 1}));
或
this.setState((currentState, currentProps)=>{
return {maxLevel: currentState.maxLevel + 1}
});
在 setState
之後,會自動呼叫 render 重繪畫面,不用自行呼叫
小結
回顧上面我們知道 React Component 中的
props
以及state
,且多了解 React Component 的constructor
,並使用這些特性,完成一個巢狀的Sample。
Refernece
Author Leefu Chen
LastMod 2018-05-07