React JS-对于许多渲染,我如何改进代码



我是React JS的新手,我正在尝试构建一个小项目来学习。到目前为止,我做得很好,但我认为我的应用程序渲染得太多了,这使我无法获得我感兴趣添加的另一个fiture——上次搜索的股票的localStorage保存。

我的项目是一个简单的股票搜索应用程序,通过股票名称或股票代码来获取股票价格。

我做错了什么?我得到了我想要的价格,但它需要太多的渲染。如果我只做一个,我得到的价格只是一个普通的0,而不是实际价格。当我像下面发布的代码一样,它显示了正确的价格,但我相信我错过了一些东西。

我对React还比较陌生,所以我想这是学习的一部分:(

我遇到的另一个问题,正如我所理解的,react router是假设保存最后输入的值。我确实使用了react路由器,这个页面上的渲染是否再次更改为默认值?

PS,当我试图将currentStock的默认状态保持为空时,我得到了一些奇怪的值,我认为这是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;

当功能组件重新提交时

在React with functional components中,每次更新状态变量时,都会导致组件重新应答(假设状态实际上与以前不同(。

因此,对于您的代码,您有以下内容:

  1. onChange={e => setCurrentStock(e.target.value)}触发的潜在转发器
  2. setCurrentPrice('Loading...');触发的潜在再应答器
  3. setCurrentStock(getSymbol.data.result[0].symbol);触发的潜在再应答器
  4. setCurrentPrice(getPrice.data.c);触发的潜在再应答器
  5. setCurrentPrice('Ready!');触发的潜在再应答器
  6. 每次依赖项更改时,effect都会重新运行

同样,如果这些set实际上没有导致状态更改,则可能不会发生这些重新应答。

我将如何编写

如果我自己写这个组件,我可能会做如下的事情。请注意,我的许多更改可能只是风格偏好。然而,将股票和符号值组合成一个状态变量可以帮助您消除重报:

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路由器

我想你关于react路由器的问题可能需要更多的细节。在您的代码中没有任何迹象表明您试图如何利用react路由器状态或将其传递到该组件中。

芬兰API

关于这个API,我认为需要注意的重要一点是/search端点真正返回字符串查询的搜索结果。因此,如果您传递一个空字符串,它将对该字符串作为搜索项运行查询并返回结果。类似地,即使输入类似APPL的内容也会有意外的结果,因为它不仅仅是在股票符号上搜索。

是的,就像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>
);
};

最新更新