# 屬性 props
在使用組件的時候,父組件可以通過`props`向子組件傳值,例如
有一個組件 `App.js` 內容如下
```jsx
import React, { Component } from 'react';
const style = {
color: '#f00'
};
class App extends Component {
render() {
return (
<div style={style}>
Hello {this.props.name}
</div>
);
}
}
export default App;
```
`index.js` 中可以通過 props 進行傳值:
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
ReactDOM.render(
<App name='xiaoyu'/>,
document.getElementById('root')
);
```
可以看到,父組件通過屬性名向子組件傳遞值,子組件中通過 `this.props.[xxx]` 取得父組件傳入的值。
## props的不可變性
Props是只讀性的,無論是使用函數或是類來聲明一個組件,它決不能修改它自己的props。所有的React組件必須像純函數那樣使用它們的props。
## 擴展屬性
如果已經有了個 props 對象,并且想在 JSX 中傳遞它,可以使用 `...` 作為擴展操作符來傳遞整個屬性對象。下面兩個組件是等效的:
```jsx
function App() {
return <Greeting firstName="Ben" lastName="Hector" />;
}
```
```jsx
function App() {
const props = {firstName: 'Ben', lastName: 'Hector'};
return <Greeting {...props} />;
}
```
## 類型檢查 PropTypes
>[warning] 注意: React.PropTypes 自 React v15.5 起已棄用。請使用 [prop-types](https://www.npmjs.com/package/prop-types) 庫代替。
隨著應用日漸龐大,你可以通過類型檢查捕獲大量錯誤。 對于某些應用來說,你還可以使用 Flow 或 TypeScript 這樣的 JavsScript 擴展來對整個應用程序進行類型檢查。
然而即使不用它們,React 也有一些內置的類型檢查功能。
首先安裝 prop-types 庫
```
npm install --save prop-types
```
使用
```jsx
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
```
### PropTypes 的驗證器
PropTypes可以使下面這些不同的驗證器:
```js
import PropTypes from 'prop-types';
MyComponent.propTypes = {
// 你可以將屬性聲明為以下 JS 原生類型
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// 任何可被渲染的元素(包括數字、字符串、子元素或數組)。
optionalNode: PropTypes.node,
// 一個 React 元素
optionalElement: PropTypes.element,
// 你也可以聲明屬性為某個類的實例,這里使用 JS 的
// instanceof 操作符實現。
optionalMessage: PropTypes.instanceOf(Message),
// 你也可以限制你的屬性值是某個特定值之一
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// 限制它為列舉類型之一的對象
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
// 一個指定元素類型的數組
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// 一個指定類型的對象
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// 一個指定屬性及其類型的對象
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// 你也可以在任何 PropTypes 屬性后面加上 `isRequired`
// 后綴,這樣如果這個屬性父組件沒有提供時,會打印警告信息
requiredFunc: PropTypes.func.isRequired,
// 任意類型的數據
requiredAny: PropTypes.any.isRequired,
// 你也可以指定一個自定義驗證器。它應該在驗證失敗時返回
// 一個 Error 對象而不是 `console.warn` 或拋出異常。
// 不過在 `oneOfType` 中它不起作用。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
// 不過你可以提供一個自定義的 `arrayOf` 或 `objectOf`
// 驗證器,它應該在驗證失敗時返回一個 Error 對象。 它被用
// 于驗證數組或對象的每個值。驗證器前兩個參數的第一個是數組
// 或對象本身,第二個是它們對應的鍵。
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})
};
```
### 屬性默認值
可以通過配置 `defaultProps` 為 props定義默認值。
```js
Greeting.defaultProps = {
name: 'Stranger'
};
```
defaultProps 用來確保 this.props.name 在父組件沒有特別指定的情況下,有一個初始值。類型檢查發生在 defaultProps 賦值之后,所以類型檢查也會應用在 defaultProps 上面。
### 案例
App.js
```js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
const style = {
color: '#f00'
};
class App extends Component {
constructor(props) {
super(props);
this.state = {
name: props.name
}
}
render() {
return (
<div style={style}>
<h2>Hello {this.state.name}</h2>
</div>
);
}
}
App.propTypes = {
name: PropTypes.string
}
export default App;
```
index.js
```js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
const name = 'xiaoyu'
ReactDOM.render(
<App name={name} />,
document.getElementById('root')
);
```
如上案例,如果傳入的 `name = 'xiaoyu'`,為一個字符串,則正常運行,但如果傳入一個非字符串的值,比如 `name = 0`,控制臺會報一個警告:
>[warning] Failed prop type: Invalid prop `name` of type `number` supplied to `App`, expected `string`.
不過程序還是會正常運行。
- 簡介
- 第一章 React入門
- 1.1 創建一個React項目
- 1.2 組件
- 1.3 JSX
- 1.4 eject
- 1.5 渲染
- 第二章 React組件
- 2.1 組件定義
- 2.2 數據處理
- 2.2.1 props
- 2.2.2 state
- 2.3 生命周期
- 2.3.1 裝載過程
- 2.3.2 更新過程
- 2.3.3 卸載過程
- 2.4 事件處理
- 2.5 條件渲染
- 2.6 列表渲染
- 第三章 React高級
- 3.1 靜態類型檢查
- 3.1.1 flow
- 3.1.2 typescript
- 3.2 React Developer Tools
- 第四章 Redux狀態管理
- 4.1 安裝與配置
- 4.2 一個簡單的計數器開始
- 4.3 Store
- 4.3.1 獲取state
- 4.3.2 subscribe
- 4.4 Action
- 4.4.1 Action Creators
- 4.5 Reducer
- 4.5.1 Reducer 的拆分
- 4.6 與其他狀態管理工具的對比
- 第五章 React-Router路由
- 參考資料