React Hooks - 如何在不影响订阅的情况下使用 useState 或 useEffect?
React Hooks - How to useState or useEffect without affecting subscription?
我正在尝试使用 web3 库从 websocket url 接收数据。然而,React Hooks 让我感到沮丧,因为它在使用 useState set 函数更新我的数组时重新呈现整个 App 函数。如何将渲染函数与 websocket 订阅分开?我不想在使用 setState 时每次都重新订阅。
这是我的代码:
function App() {
console.log('init');
const [blocks, setBlock] = useState([]);
(async () => {
const web3 = new Web3(new
Web3.providers.WebsocketProvider('wss...'));
web3.eth.subscribe('newBlockHeaders', async (error, blockHeader) => {
const block = await web3.eth.getBlock(blockHeader.hash, true);
setBlock([...blocks, block.number]);
console.log(blocks);
});
})();
return (
<div className = "App">
<header className = "App-header">
<p>{ blocks }</p>
</header>
</div>
);
}
我认为你应该使用 useCallback
和 useEffect
const subscribe = useCallback(async () => {
const web3 = new Web3(new Web3.providers.WebsocketProvider('wss...'));
web3.eth.subscribe('newBlockHeaders', async (error, blockHeader) => {
const block = await web3.eth.getBlock(blockHeader.hash, true);
setBlock([...blocks, block.number]);
console.log(blocks);
});
}, [])
useEffect(() => {
subscribe()
}, [])
使用安装 useEffect
挂钩(即 w/empty 依赖数组)来处理订阅。 Return 取消订阅的清理功能。 useEffect
挂钩运行 一次 来设置订阅,当组件 卸载时 调用清理函数取消订阅
使用功能状态更新将新块编号添加到 blocks
状态。当设置订阅的 newBlockHeaders
事件侦听器回调时,功能状态更新避免了 blocks
状态值的陈旧封闭,它传递先前的状态以进行更新。
function App() {
const [blocks, setBlock] = useState([]);
useEffect(() => {
const web3 = new Web3(new Web3.providers.WebsocketProvider('wss...'));
const sub = web3.eth.subscribe(
'newBlockHeaders',
async (error, blockHeader) => {
const block = await web3.eth.getBlock(blockHeader.hash, true);
setBlock(blocks => [...blocks, block.number]);
},
);
return () => sub.unsubscribe();
}, []);
return (
<div className = "App">
<header className = "App-header">
<p>{ blocks }</p>
</header>
</div>
);
}
我正在尝试使用 web3 库从 websocket url 接收数据。然而,React Hooks 让我感到沮丧,因为它在使用 useState set 函数更新我的数组时重新呈现整个 App 函数。如何将渲染函数与 websocket 订阅分开?我不想在使用 setState 时每次都重新订阅。
这是我的代码:
function App() {
console.log('init');
const [blocks, setBlock] = useState([]);
(async () => {
const web3 = new Web3(new
Web3.providers.WebsocketProvider('wss...'));
web3.eth.subscribe('newBlockHeaders', async (error, blockHeader) => {
const block = await web3.eth.getBlock(blockHeader.hash, true);
setBlock([...blocks, block.number]);
console.log(blocks);
});
})();
return (
<div className = "App">
<header className = "App-header">
<p>{ blocks }</p>
</header>
</div>
);
}
我认为你应该使用 useCallback
和 useEffect
const subscribe = useCallback(async () => {
const web3 = new Web3(new Web3.providers.WebsocketProvider('wss...'));
web3.eth.subscribe('newBlockHeaders', async (error, blockHeader) => {
const block = await web3.eth.getBlock(blockHeader.hash, true);
setBlock([...blocks, block.number]);
console.log(blocks);
});
}, [])
useEffect(() => {
subscribe()
}, [])
使用安装 useEffect
挂钩(即 w/empty 依赖数组)来处理订阅。 Return 取消订阅的清理功能。 useEffect
挂钩运行 一次 来设置订阅,当组件 卸载时 调用清理函数取消订阅
使用功能状态更新将新块编号添加到 blocks
状态。当设置订阅的 newBlockHeaders
事件侦听器回调时,功能状态更新避免了 blocks
状态值的陈旧封闭,它传递先前的状态以进行更新。
function App() {
const [blocks, setBlock] = useState([]);
useEffect(() => {
const web3 = new Web3(new Web3.providers.WebsocketProvider('wss...'));
const sub = web3.eth.subscribe(
'newBlockHeaders',
async (error, blockHeader) => {
const block = await web3.eth.getBlock(blockHeader.hash, true);
setBlock(blocks => [...blocks, block.number]);
},
);
return () => sub.unsubscribe();
}, []);
return (
<div className = "App">
<header className = "App-header">
<p>{ blocks }</p>
</header>
</div>
);
}