Bluetom

Time Slicing 和Suspense实现

time slice时间分片,render不会阻塞线程,整段渲染

Suspense主要解决网络io问题,避免redux、soga库的副作用,以同步方式写异步组件。

最应用的例子就是:一张图片加载,抖动内容区域。用Suspense就可以完美解决,在图片加载完后,render整个区域。

具体实现可以看这里createFeatcher

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const getBulbasaur = () =>
fetch("https://pokeapi.co/api/v2/pokemon/1/").then(res => res.json());

const ApiResource = createResource(getBulbasaur);

const Pokemon = () => {
const bulbasaur = ApiResource.read();

return <div>Hello {bulbasaur.name}</div>;
};

const App = () => (
<Suspense fallback={<div>Let's wait :D</div>}>
<Pokemon />
</Suspense>
);

禁止capture value特性

示例代码,输入123后,再点击send按钮,再3s结束前飞速输入aaa,alert出来的猜猜是。

由于useState获取到的是send按钮时的message,所以并不是123aaa,而是123

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function MessageThread() {
const [message, setMessage] = useState("");

const showMessage = () => {
alert("You said: " + message);
};

const handleSendClick = () => {
setTimeout(showMessage, 3000);
};

const handleMessageChange = e => {
setMessage(e.target.value);
};

return (
<>
<input value={message} onChange={handleMessageChange} />
<button onClick={handleSendClick}>Send</button>
</>
);
}

使用useRef来规避

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function MessageThread() {
const latestMessage = useRef("");

const showMessage = () => {
alert("You said: " + latestMessage.current);
};

const handleSendClick = () => {
setTimeout(showMessage, 3000);
};

const handleMessageChange = e => {
latestMessage.current = e.target.value;
};
}

规避setInterval问题

三种解决办法

1.useEffect调用,传入引用值

1
2
3
4
5
6
7
8
9
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = setTimeout(() => {
setTime(time + 1);
}, 1000);
return () => {
clearInterval(timer);
};
}, [time]);

2.手写useInterval

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 使用useInterval代替setInterval

const useInterval = (callback, delay) => {
const sourceVCallback = useRef();

useEffect(() => {
sourceCallback.current = callback;
}, [callback]);

useEffect(() => {
const tick = () => sourceVCallback.current();

if (delay !== null) {
id = setInterval(tick, delay);
return clearInterval(id);
}
}, [delay]);
}

3.useEffect中已回调更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Clock() {
const [time, setTime] = React.useState(0);
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(prevTime => prevTime + 1); // <-- Change this line!
}, 1000);
return () => {
window.clearInterval(timer);
};
}, []);

return (
<div>Seconds: {time}</div>
);
}

Bluetom

作为挨踢业的前段湿 搬过砖也画过画:爱看、爱听、爱玩儿、爱折腾、爱打撸啊撸、intj

Proudly published with Hexo