[英]React JS - To many renderings, how can I improve that code?
我是 React JS 的新手,我正在嘗試構建一個小項目來學習。 到目前為止,我做得很好,但我相信我的應用程序渲染太多,它阻止了我獲得另一個我有興趣添加的設備 - 最后一個搜索股票的 localStorage 保存。
我的項目是一個簡單的股票搜索應用程序,通過股票名稱或股票代碼獲取股票價格。
我究竟做錯了什么? 我得到了我想要的價格,但是它需要太多的效果圖。 如果我只做一個,我得到的價格只是一個簡單的 0,而不是實際價格。 當我像下面發布的代碼一樣 go 時,它顯示了正確的價格,但我相信我錯過了一些東西。
我對 React 比較陌生,所以我猜這是學習的一部分:)
據我了解,我的另一個問題是 react-router 應該保存最后輸入的值。 我確實使用了反應路由器,此頁面上的渲染是否再次更改為默認值?
PS,當我嘗試將 currentStock 的默認 state 保留為空時,我得到了一些奇怪的值,我認為這是 API 本身的問題。
這是我的代碼:
const Stocks = () => {
const [currentStock, setCurrentStock] = useState('AAPL');
const [currentPrice, setCurrentPrice] = useState('Loading...');
const [stockFromClick, setClick] = useState();
useEffect( () => {
if(currentPrice === 0){
setCurrentPrice('Ready!')
}
const fetchData = async() =>{
const getSymbol = await axios(`https://finnhub.io/api/v1/search?q=${currentStock}&token=${API_KEY}`);
setCurrentStock(getSymbol.data.result[0].symbol);
const getPrice = await axios (`https://finnhub.io/api/v1/quote?symbol=${currentStock}&token=${API_KEY}`)
setCurrentPrice(getPrice.data.c)
}
fetchData();
console.log(currentPrice);
} , [stockFromClick, currentPrice]);
const handleClick = () =>{
setCurrentPrice('Loading... Please allow the system a few seconds to gather all the information');
setClick(currentStock);
console.log(currentStock);
}
return (
<div>
Stocks!<br></br>
<input type="text" placeholder="Search a Company" value={currentStock} onChange={e => setCurrentStock(e.target.value)} /><br></br>
<button type="button" onClick={handleClick}> Search</button><br></br>
{currentPrice}
</div>
)
}
export default Stocks;
是的,就像 WebbH 每次設置 currentPrice 時都會重新渲染......我想我會嘗試使用切換來加載
const Stocks = () => {
const [currentStock, setCurrentStock] = useState("apple");
const [currentPrice, setCurrentPrice] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const fetchData = async () => {
if (!isLoading) setIsLoading(true);
try {
const getSymbol = await axios.get(
`https://finnhub.io/api/v1/search?q=${currentStock}&token=${API_KEY}`
);
setCurrentStock(getSymbol.data.result[0].symbol);
const getPrice = await axios.get(
`https://finnhub.io/api/v1/quote?
symbol=${currentStock}&token=${API_KEY}`
);
setCurrentPrice(getPrice.data.c);
setIsLoading(false);
} catch (error) {
console.log("fetchData: ", error);
}
};
useEffect(() => {
fetchData();
}, []);
const handleClick = () => {
fetchData();
};
return (
<div>
...
<br></br>
{isLoading && !currentPrice
? "Loading... Please allow the system a few seconds to gather all the
information"
: { currentPrice }}
</div>
);
};
功能組件何時重新渲染
在 React with functional components 中,每次更新 state 變量時,都會導致組件重新呈現(假設 state 實際上與以前不同)。
因此,使用您的代碼,您將擁有以下內容:
onChange={e => setCurrentStock(e.target.value)}
觸發的潛在重新渲染setCurrentPrice('Loading...');
setCurrentStock(getSymbol.data.result[0].symbol);
setCurrentPrice(getPrice.data.c);
setCurrentPrice('Ready;');
effect
都會重新運行。 同樣,如果這些set
實際上沒有導致 state 發生更改,則可能不會發生這些重新渲染。
我會怎么寫
如果我要自己編寫這個組件,我可能會執行以下操作。 請注意,我的許多更改可能只是風格偏好。 但是,將股票和代碼值組合到單個 state 變量中可以幫助您消除重新渲染:
import { useState, useEffect, useCallback } from 'react';
import axios from 'axios';
const Stocks = () => {
const [isLoading, setIsLoading] = useState(false);
const [stock, setStock] = useState({});
const [query, setQuery] = useState('APPL');
const fetchData = useCallback(async (q) => {
// don't do anything if we don't have a query string
if (!q) return;
setIsLoading(true);
const getSymbol = await axios(`https://finnhub.io/api/v1/search?q=${q}&token=${API_KEY}`);
const symbol = getSymbol.data.result[0].symbol;
const getPrice = await axios(`https://finnhub.io/api/v1/quote?symbol=${symbol}&token=${API_KEY}`);
const price = getPrice.data.c;
setStock({ symbol, price });
setIsLoading(false);
}, []);
// load the default stock data on initial rendering
useEffect(() => fetchData(query), []);
return (
<div>
Stocks! <br/><br/>
<label for="query">Search For A Stock:</label>
<input
name="query"
type="text"
placeholder="Ex. APPL"
value={query}
onChange={e => setQuery(e.target.value)}
/>
<br></br >
<button
type="button"
onClick={() => fetchData(query)}
>Search</button>
<br/><br/>
{isLoading && <span>Loading... Please allow the system a few seconds to gather all the information</span>}
{!isLoading &&
<div>
<div>Symbol: {stock.symbol}</div>
<div>Price: {stock.price}</div>
</div>
}
</div>
);
}
export default Stocks;
反應路由器
我認為您關於 react-router 的問題可能需要更多細節。 您的代碼中沒有任何跡象表明您是如何嘗試利用 react-router state 或將其傳遞到此組件中的。
Finnhub API
我認為關於這個 API 需要注意的重要一點是/search
端點真正返回了字符串查詢的搜索結果。 因此,如果您傳遞一個空字符串,它將作為搜索詞運行一個查詢並返回結果。 同樣,即使輸入APPL
之類的內容也會產生意想不到的結果,因為它不僅僅是搜索股票代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.