之前用的 Component 都是用 class 的形式來寫 ( Class Component
),而其實有另外一種方式寫 Component,叫做 functional Component
。
以下是 Counter
這個 Component 用不同形式來寫:
/* Class Component */
class Counter extends Component {
render() {
console.log('Counter-render');
return <div>{this.props.number}</div>;
}
}
/* Functional Component */
function Counter(props) { // => 一樣有 props 的屬性可以使用
return <div>{props.number}</div>
}
/* Functional Component - 或是更進階一點,使用解構語法 */
function Counter({number}) { // => 其實就是 const {number} = props
return <div>{number}</div>
}
那寫 Component 時要怎麼決定用哪種寫法呢?
有個很簡單的判斷技巧是,當你只是要寫個很單純的 Component,不需要儲存 state
也沒有其他事件監聽,功能只有 render
畫面時,就很適合用 Functional Component,因為語法比起 Class Component 會比較簡潔一點。
在 React 裡面, children Component 是沒有辦法改變 parent Component 的 state
,所以最好的方式是把 parent 改變 state
的 function 傳下去給 children,當成其中一個 props 的屬性。
const Title = (props) => {
return (
// => 接收到 App 傳來的 handleClick,才能藉此改變 App 的 state
<h1 onClick={props.handleClick}>{props.text}</h1>
)
}
class App extends Component {
constructor() {
super();
this.state = {
counter : 1
}
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
counter: this.state.counter + 1
})
}
render() {
return (
<div>
// => 把能夠改變 state 的 handleClick 傳給 Title
<Title handleClick={this.handleClick} text={this.state.counter}/>
</div>
)
}
}
此時不斷得點擊 <h1>
就可以看到數字增加。
See the Pen [React] change state by props by Yakim Shu (@yakim-shu) on CodePen.
App's state.counter: 1
App.handleClick: func
App.handleClick
counter : 2
App's state.counter: 2
props
所以重點是當 children Component <Title />
要更新傳遞進來的 props
時,是沒有辦法直接對 props
做更改的,必須透過 parent Component <App />
傳遞進來的 function 做更新才行。
把剛剛的範例改寫成「 每點一次,counter 就變成一個隨機數 」,示範傳進去的 function 有帶參數的例子,變成很像在寫 callback function:
const Title = (props) => {
return (
<h1 onClick={() => {
props.changeCounter(Math.random()) // => 就像一個 callback function 的寫法
}}>{props.text}</h1>
)
}
class App extends Component {
constructor() {
super();
this.state = {
counter : 1
}
this.changeCounter = this.changeCounter.bind(this); // => 不要忘了 bind
}
changeCounter(num) {
this.setState({
counter: num
})
}
render() {
return (
<div>
// => 一樣把能夠改變 App state 的 function 傳進去
<Title changeCounter={this.changeCounter} text={this.state.counter}/>
</div>
)
}
}
See the Pen [React] change state with random number by props by Yakim Shu (@yakim-shu) on CodePen.
所以要記住的重要觀念就是,只有 Component 可以改變自己的 state,如果要改變其他 Component 的 state ,只有該 Component 有提供的方法才可行。
( 以上內容大部分是 程式導師實驗計畫第三期 的學習筆記,如有錯誤歡迎糾正,非常感謝 🤓 )
Written on September 11th, 2019 by Yakim shu