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>
)
}
}
image.png
在不停的点击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'
/>
</>
);
}
image.png
先点击 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'
/>
</>
);
}
image.png
React .forwardRef
React.forwardRef
会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特别有用:
React.forwardRef
接受渲染函数作为参数。React 将使用 props
和 ref
作为参数来调用此函数。此函数应返回 React 节点。
网友评论