author: 軒邈javascript
eg: const [count, setCount] = useState(0)html
介紹java
(1)有一個參數:默認值, 能夠是函數,只在初始渲染時執行一次node
(2)返回一個帶有兩個元素的數組react
(3)第一個元素是 state 的值, 第二個元素是更新state的函數,每次新的,使用useCallback,可讓它使用上次的函數;函數名隨意不必定是set某某某,參數能夠是要更新的值或者函數,當是函數時,函數參數是上一次state的值。git
(4) 若是有多個state則根據 useState 的調用順序來「記住」每一個state的狀態歸屬
(5)這個特性要求Hooks不能夠寫在if或者switch等可能不執行的代碼片斷,會致使調用次序不一致
複製代碼
簽名與 useEffect 相同,在DOM變化(layout佈局)後同步觸發,渲染之前(paint繪製)執行 ,適用於用戶可見的 DOM 改變。github
與 componentDidMount
和 componentDidUpdate
不一樣,傳遞給 useEffect
的函數在DOM變化(layout佈局) 和渲染(paint繪製)後觸發。 這使得它適用於許多常見的 side effects ,例如設置訂閱和事件處理程序,由於大多數類型的工做不該阻止瀏覽器更新(判斷標準)屏幕。redux
`componentDidMount: useLayoutEffect(() => {setTitle(1)}, [])`
`componentDidUpdate: useLayoutEffect(() => {console.log(1)})`
`componentWillUnmount: useLayoutEffect()=>{return () => {console.log('我要卸載組件啦')}}`
我是一個方法,組件更新後返回,下次組件更新前執行:`useLayoutEffect(() => {return () => {console.log(‘我是一個方法,組件更新後返回,下次組件更新前執行')}}, [count, count2])`
複製代碼
1. 第一個爲函數,默認會在渲染完成後執行一次,若是返回的是一個函數,則返回的函數會在第二個參數數組裏面的元素髮生變化且渲染完成後執行
2. 第二個爲一個數組(也能夠寫成常量等類型,不過不會調用參數一),裏面寫須要監控的state,當state改變時會調用第一個函數,不改變則不會調用參數一,當數組爲空時,只會在最開始調用一次,至關於componentDidMount;不傳時,默認監控全部state,至關於componentDidUpdate
複製代碼
const theme = useContext(ThemeContext)
複製代碼
```javascript
const ThemeContext = React.createContext();
const LanguageContext = React.createContext();
```
```js
<ThemeContext.Consumer>
{
theme => (
<LanguageContext.Cosumer>
language => {
//可使用theme和lanugage了
}
</LanguageContext.Cosumer>
)
}
</ThemeContext.Consumer>
```
兩個render props寫法,兩個嵌套看起來麻煩不少
使用useContext時
```js
const theme = useContext(ThemeContext);
const language = useContext(LanguageContext);
// 這裏就能夠用theme和language了
```
接受一個由React.createContext返回的上下文對象,寫法簡化不少而且再也不須要理解render props
複製代碼
```javascript
const ThemedPage = () => {
const theme = useContext(ThemeContext);
return (
<div>
<Header color={theme.color} />
<Content color={theme.color}/>
<Footer color={theme.color}/>
</div>
);
};
```
當theme的其餘屬性(如size等其餘非color屬性)改變時也會致使界面從新渲染
複製代碼
```javascript
const initialState = { count: 0 }
const reducer = function reducer(state, action) {
switch (action.type) {
case 'reset':
return initialState
case 'increment':
return { ...state, count: state.count + 1 }
case 'decrement':
return { ...state, count: state.count - 1 }
default:
return state
}
}
```
//上面這部分應該寫在函數組件外面防止函數一遍遍的建立
const [count3, count3Dispatch] = useReducer(reducer, initialState)
複製代碼
```javascript
const [count4, setCount4] = useState(0)
const counterRef = useRef(count4)
useEffect(
() => {
counterRef.current = count4
},
[count4]
)
const incrementCount4 = useCallback(() => setCount4(counterRef.current + 1), [])
```
複製代碼
介紹:useCallback(fn, inputs) 等價於 useMemo(() => fn, inputs)小程序
介紹:useRef 返回一個可變的 ref 對象,其 .current 屬性被初始化爲傳遞的參數(initialValue)。返回的對象將存留在整個組件的生命週期中。react-native
```javascript
// eg:
const useMountLog = name => {
useEffect(() => {
console.log(`${this.name}組件渲染時間->${this.end - this.begin}ms`)
},[])
}
```
複製代碼
// eg: usePrevious
function usePrevious(value) {
const ref = useRef()
useEffect(() => {
ref.current = value
})
return ref.current
}
複製代碼
packages/shared
目錄下全部文件中的enableHooks = false
替換爲enableHooks = true
yarn install
yarn build -- --type=RN_OSS
build/react-native/
下的內容替換 項目路徑/node_modules/react-native/Libraries/Renderer
(我使用時react-native版本爲0.57.8)下的內容替換類組件
// 改造前
export default class HomeScene extends Component{...}
// 改造後
export default forwardRef((props, ref) => {...}) // forwardRef包起來是方便函數組件內部方法調用
複製代碼
構造函數移除
state狀態修改和建立改成useState const [visible, setVisible] = useState(false)
改造前父組件經過ref引用子組件的方法,改造後使用forwardRef
將createRef建立的ref傳遞到子組件內部,再使用useImperativeMethods將內部方法綁定到傳進來的ref上
useImperativeMethods(ref, () => ({ showModal: this.showModal }), [])
複製代碼
方法
// 改造前
showModal = (from, data, ticket) => {...}
// 改造後
this.showModal = (from, data, ticket) => {...} // 推薦使用箭頭函數方便函數間調用
複製代碼
render改成return,按state狀態變化將原先render前的邏輯移入對應useEffect。
(1)引入StoreContext將根組件包起來
<StoreContext.Provider value={store}>
...
</StoreContext.Provider>
複製代碼
(2)```javascript // 改造前 const { name, cityName } = this.props.UserInfo // 改造後 const mapState = React.useCallback(state => state.UserInfo, []) const { name, cityName } = useMappedState(mapState)
(3)每次調用useMappedState都會執行subscribe store。 可是,若是store更新,你的組件將只從新渲染一次。 所以,屢次調用useMappedState(例如封裝在自定義hooks中)不該該對性能產生很大影響。 若是測試發現性能影響較大,能夠嘗試返回對象。
複製代碼
引入react-navigation-hooks,需升級react-navigation至最新版(3.1.0)適配。
(1)使用
```javaScript
const { navigate } = useNavigation()
```
與原先的路由管理共用一套路由
複製代碼
(2)注意:
1) 若是項目是用pod管理,該RNGestureHandler.podspec裏面路徑有問題須要修改。
2) createBottomTabNavigator的第二個參數BottomTabNavigatorConfig的navigationOptions屬性改成了defaultNavigationOptions
複製代碼
target.$$typeof === Symbol.for('react.forward_ref')
(我暫時是這樣處理的)useCallback
包裹,並傳一個空數組,來保證永遠只監聽一次,並且不須要在組件銷燬時註銷這個 callback。原文連接: tech.meicai.cn/detail/81, 也可微信搜索小程序「美菜產品技術團隊」,乾貨滿滿且每週更新,想學習技術的你不要錯過哦。