簡體   English   中英

React JS - 對於許多渲染,我該如何改進該代碼?

[英]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 實際上與以前不同)。

因此,使用您的代碼,您將擁有以下內容:

  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實際上沒有導致 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM