iT邦幫忙

2021 iThome 鐵人賽

DAY 8
0
Modern Web

用React刻自己的投資Dashboard系列 第 8

用React刻自己的投資Dashboard Day8 - useState hook

tags: 2021鐵人賽 React

在Card元件中有使用到useState,是React中一個蠻重要的hook,是一個非常強大的功能,看起來跟用起來都非常的簡潔,這篇就來分析一下useState的用法及背後的原理。

Hook是什麼

引用自React官網

Hook 是 React 16.8 中增加的新功能。它讓你不必寫 class 就能使用 state 以及其他 React 的功能。

然後很棒的一點是向下相容class,react官網也有說明三點如下:

  • 完全自由選擇使用。你可以在幾個 component 中試用 Hook 而不用重寫任何既有的程式碼。不過如果你不想要,並不需要現在學習或使用 Hook。
  • 100% 向下相容。Hook 沒有任何 breaking change。
  • 目前沒有計畫要從 React 移除 class。

useState hook範例

這邊就寫個範例來認識hook跟class在使用上有什麼不同:

  • 程式碼比較圖
    這個範例是點擊按鈕之後,點擊次數會加1,是個相當簡單的例子。程式碼比較如下圖,左邊是class版本,右邊是hook版本。可以發現class版本的程式碼稍微比較長一些,不過這個範例只有定義一個state,如果同時有很多個state需要管理的時候,那程式碼的數量就會差很多。另外就是一個是用class component,一個是用function component,這個要比較的話又可以再寫一篇文章,這邊就先省略。

    如果想要實際測試的朋友,這邊提供兩個codepen可以參考:
    * class版本:https://codepen.io/siang720/pen/VwbOzby
    * hook版本:https://codepen.io/siang720/pen/eYWaGwj

  • useState使用方式

    • 宣告state的方式如下程式碼,useState會回傳一個array,裡面有兩個element,下面這行的意思就是讓count與setCount去對應回傳的兩個element,而state的初始值是0。count就是要管理的state,setCount則是用來做狀態管理的函數,這兩個變數是可以任意命名的。
    const [count, setCount] = useState(0);
    
    • 變更state的方式:如範例中的程式碼,呼叫setCount,並將調整state的方式放在括號內,這個例子裏面調整count這個state的方式就是讓它等於原本的值再加上1。
    const buttonClickHandler = () => {
        setCount(count + 1)
    };
    
    • 重新渲染:一旦state的狀態被改變之後,react就會重新渲染有改變的element。

state也可以是一個物件

上述的範例的state是一個number,不過其實state還可以是object,如同Day6裡面的Card.js,裡面所管理的state就是一個物件。我將highchart要用到的option寫成一個state來管理,因為option裡面要引入數據,而數據需要call api取得,因此我希望call完api之後,將得到的數據放入state,讓react可以知道有東西更新了,就會去重新渲染圖表。

Card.js

const Card = (props) => {
  // 定義state
  const [chartOption, setChartOption] = useState({
    title: {
      text: props.item.title
    },
    xAxis: {
      type: "datetime",
      title: {
        text: 'Date'
      }
    }
  });

  // 抓取資料
  const fetchData = (series_id) => {
    fetch(`${process.env.REACT_APP_PROXY_SERVER_URL}/series/observations?series_id=${series_id}&api_key=${process.env.REACT_APP_API_KEY}&file_type=json`, {
      headers: {
        'Target-URL': 'https://api.stlouisfed.org/fred'
      }
    })
      .then((response) => response.json())
      .then((data) => {
        let data1 = [];
        data.observations.forEach(ob => {
          data1.push([new Date(ob.date).getTime(), Number(ob.value)]);
        });
        
        // 將數據導入option state
        setChartOption((prevOption) => {
          return {
            ...prevOption,
            series: [
              {
                name: props.item.title,
                data: data1
              }
            ]
          }
        })
      });
  };
  
  // 另外一個hook,下一篇說明,功能是用來讓網頁一載入即call api抓資料
  useEffect(() => {
    fetchData(props.item.series_id);
  }, []);

  return (
    <div className={styles.chartFrame}>
      <HighchartsReact
        highcharts={Highcharts}
        constructorType={'stockChart'}
        options={chartOption}
      />
      <div className={styles.chartInfo}>
        <p className={styles.source}>source: {props.item.source}</p>
        <p className={styles.date}>updated: {props.item.updated}</p>
      </div>
      <div>
        <p className={styles.document}>{props.item.document}</p>
      </div>
    </div>
  )
}

export default Card;

上面程式碼宣告state的部分擷取如下:

  // 定義state
  const [chartOption, setChartOption] = useState({
    title: {
      text: props.item.title
    },
    xAxis: {
      type: "datetime",
      title: {
        text: 'Date'
      }
    }
  })

這個state為了符合highchart套件的格式,所以看起來稍微複雜了一些。

將數據導入state的程式碼擷取如下:
prevOption指得是既有的state狀態,這邊做的是不變更既有的狀態,在option內加series。

setChartOption((prevOption) => {
  return {
    ...prevOption,
    series: [
      {
        name: props.item.title,
        data: data1
      }
    ]
  }
})

所以經由setChertOption修改後,chartOption應該會是下面這樣:

{
    title: {
      text: props.item.title
    },
    xAxis: {
      type: "datetime",
      title: {
        text: 'Date'
      }
    },
    series: [
      {
        name: props.item.title,
        data: data1
      }
    ]
 }

小結

useState看起來非常的簡潔,真的是一個很棒的hook,下一篇就來介紹一下這篇還沒講到的useEffect hook,它可以解釋為什麼進入網頁後,react會自動去抓取資料並且呈現在圖表上。


上一篇
用React刻自己的投資Dashboard Day7 - CORS與Proxy Server
下一篇
用React刻自己的投資Dashboard Day9 - useEffect hook
系列文
用React刻自己的投資Dashboard30

尚未有邦友留言

立即登入留言