2021鐵人賽
React
在Card元件中有使用到useState,是React中一個蠻重要的hook,是一個非常強大的功能,看起來跟用起來都非常的簡潔,這篇就來分析一下useState的用法及背後的原理。
引用自React官網
Hook 是 React 16.8 中增加的新功能。它讓你不必寫 class 就能使用 state 以及其他 React 的功能。
然後很棒的一點是向下相容class,react官網也有說明三點如下:
這邊就寫個範例來認識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使用方式
const [count, setCount] = useState(0);
const buttonClickHandler = () => {
setCount(count + 1)
};
上述的範例的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會自動去抓取資料並且呈現在圖表上。