useState
import React, { useState } from "react";
function App() {
const [obj, setObject] = useState({
count: 0,
name: "alife"
});
return (
<div className="App">
Count: {obj.count}
<button onClick={() => setObject({ ...obj, count: obj.count + 1 })}>+</button>
<button onClick={() => setObject({ ...obj, count: obj.count - 1 })}>-</button>
</div>
);
useEffect
import React, { useState, useEffect } from "react";
let timer = null;
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = "componentDidMount" + count;
},[count]);
useEffect(() => {
timer = setInterval(() => {
setCount(prevCount => prevCount + 1);
}, 1000);
return () => {
document.title = "componentWillUnmount";
clearInterval(timer);
};
}, []);
return (
<div>
Count: {count}
<button onClick={() => clearInterval(timer)}>clear</button>
</div>
);
}
useContext 減少組件層級
const colorContext = React.createContext("gray");
function Bar() {
const color = useContext(colorContext);
return <div>{color}</div>;
}
function Foo() {
return <Bar />;
}
function App() {
return (
<colorContext.Provider value={"red"}>
<Foo />
</colorContext.Provider>
);
}
useMemo 先看一個例子
export default class a extends React.Component {
state = {
num: 1
}
handleClick = () => {
const { num } = this.state;
this.setState({
num: num + 1
})
}
handTestClick = () => {
}
renderTest = () => {
console.log('函數組件渲染')
return (
<Text>
function Children
</Text>
)
}
render() {
const { num } = this.state;
return (
<View style={{ display: "flex", justifyContent: "center", alignItems: "center", flex: 1 }}>
<TouchableOpacity style={{ color: "#333", fontSize: 20 }} onPress={this.handleClick}>
<Text>{num}</Text>
</TouchableOpacity>
{this.renderTest()}
<Test onClick={this.handTestClick} />
</View>
)
}
}
在不停的點擊handleClick的時候,函數式組件不停的渲染,如果這個函數式組件返回比較複雜的時候,會造成性能損耗,用
useMemo 來返回一個記憶函數
同時你也可以根據第二個參數,第二個參數傳入一個數組,數組中的每一項一旦值或者引用發生改變,useMemo 就會重新返回一個新的記憶函數提供給後面進行渲染。
import React, {useMemo, useState, useCallback ,useEffect} from 'react';
import {
Text,
View,
TouchableOpacity
} from 'react-native';
import Test from './components/Test'
export default () => {
const [num, useNum] = useState(1)
const handleClick = () => {
useNum(num + 1)
}
const handTestClick = () => {
}
const renderTest = useMemo(() => {
console.log('函數組件渲染')
return (
<Text>
function Children
</Text>
)
},[])
return (
<View style={{ display: "flex", justifyContent: "center", alignItems: "center", flex: 1 }}>
<TouchableOpacity style={{ color: "#333", fontSize: 20 }} onPress={handleClick}>
<Text>{num}</Text>
</TouchableOpacity>
{renderTest}
<Test onClick={handTestClick} />
</View>
)
}
Capture Value 特性
看一個類組件
import React, { useEffect, useState } from 'react';
import {
Button,
TextInput
} from 'react-native';
export default class a extends React.Component {
state={
message:''
}
showMessage = () => {
const { message } = this.state
alert("You said: " + message);
};
handleMessageChange = e => {
this.setState({
message: e
})
};
handleSendClick = () => {
setTimeout(this.showMessage, 3000);
};
render() {
const { message } = this.state;
return (
<>
<TextInput style={{ height: 40, width: 200 }} value={message} onChangeText={this.handleMessageChange} />
<Button
onPress={this.handleSendClick}
title='Send'
/>
</>
);
}
}
先點擊Send 按鈕後,再次修改輸入框的值,3 秒後的輸出的結果是期望值,因爲這時候 message 是掛載在 this 變量上,它保留的是一個引用值,對 this 屬性的訪問都會獲取到最新的值
看下函數式組件
export default function(props) {
const [message, setMessage] = useState('');
const showMessage = () => {
alert("You said: " + message);
};
const handleSendClick = () => {
setTimeout(showMessage, 3000);
};
const handleMessageChange = e => {
console.log(e)
setMessage(e);
};
return (
<>
<TextInput style={{height:40,width:200}} value={message} onChangeText={handleMessageChange} />
<Button
onPress={handleSendClick}
title='Send'
/>
</>
);
}
先點擊 Send 按鈕後,再次修改輸入框的值,3 秒後的輸出依然是點擊前輸入框的值。這就是所謂的 capture value 的特性 useRef 創建一個引用,就可以有效規避 React Hooks 中 Capture Value 特性。
如何規避 React Hooks 中 Capture Value 特性 ?
使用
useRef 創建一個引用 只要將賦值與取值的對象變成 useRef,而不是 useState,就可以躲過 capture value 特性,在 3 秒後得到最新的值。
export default function (props) {
const latestMessage = useRef();
const [message, setMessage] = useState('');
const showMessage = () => {
console.log(latestMessage)
const { props:{value} } = latestMessage.current
alert("You said: " + value);
};
const handleSendClick = () => {
setTimeout(showMessage, 3000);
};
const handleMessageChange = e => {
console.log(e)
setMessage(e);
};
return (
<>
<TextInput ref={latestMessage} style={{ height: 40, width: 200 }} value={message} onChangeText={handleMessageChange} />
<Button
onPress={handleSendClick}
title='Send'
/>
</>
);
}
React .forwardRef
React.forwardRef
會創建一個React組件,這個組件能夠將其接受的 ref 屬性轉發到其組件樹下的另一個組件中。這種技術並不常見,但在以下兩種場景中特別有用:
React.forwardRef
接受渲染函數作爲參數。React 將使用 props
和 ref
作爲參數來調用此函數。此函數應返回 React 節點。