---
# System prepended metadata

title: 3. State/props/refs
tags: [React]

---

# 3. State/props/refs
###### tags: `React`

* 組件名稱必須為大寫開頭
* react 解析組件標籤後找到Demo
> function Component
 ->調用Weather()將回傳的虛擬Dom轉為真實Dom
 
 原 : 無法有state
 hook : `const [statename,setstate]=useState()`
     (State hook 也是一種解構賦值的寫法)
```
function Weather(){
    const [count, setCount] = useState(0); //State hook
	return <h1>test</h1>;//必須有傳回值
}
```
> Class Component
 ->組件使用類定義 : new出來該類的實例，並且調用原型物件上的render方法
```
class Weather extends React.Component{
/*
    constructor(props){
		super(props)
		this.state = {count:0}
		this.changeWeather = this.changeWeather.bind(this)
	} 
*/
	state = {count:0}
	render(){
		return 
	}
	changeWeather = ()=>{
	}
}
```
* render()中的this 為該組件的物件實例(Weather)
` Weather.render()`
* 組件自定義方法中this為undefined
	a) 強制綁定this: 通過函數對象的bind()
	b) 箭頭函數
---
> State

不能直接修改或更新，需呼叫`setState()`

---
> props

通過標籤屬性從組件外向組件內傳遞data
* 組件內部不可修改props數據
* 取值
	```
	name = this.props.name
	password= this.props.password
	```
	`{name,password}=this.props` (解構賦值)
    `<a {...this.props}>{this.props.children}<a/>`
    一口氣將所有的props放入<a>的屬性。
    透過.children取得上層標籤body的內容。
    
* 賦值
    1. 最基本寫法 要注意如果傳入值有形別則要用{}的方式型別才會正確
    `<Demo name="tom" age={10} / >`
    2. 擴展屬性:
        與es的展開運算符不同，雖然結果是展開物件，但這是babel與react特有的定義且只有在標籤中有效
		```
		person={name:"",ps:"",gender:""}
		<Person {...person}/>
		```
    3. tag body -> children屬性
    `<a>標籤體<a/>` = `<a children="標籤體"/>`
    
* 限制props
需[prop-types](https://www.npmjs.com/package/prop-types)(npm install --save prop-types)
```
Person.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number.
}
```
* 默認屬性值：
```
 Person.defaultProps = {
  age: 18,
  sex:'男'
}
```
---
> refs
組件內的標籤可以定義ref屬性來標識自己
1. 字符串形式的ref (不推薦使用)
` <input ref="input1"/>`
2. callback形式的ref
` <input ref={(c)=>{this.input1 = c}}`
3. createRef創建ref容器·
```
 myRef = React.createRef()
<input ref={this.myRef}/>
```