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> ); }
|