7-6 讓使用者可以自行設定地區
本單元對應的專案分支為:select-location-in-weather-setting。
單元核心#
這個單元的主要目標包含:
- 讓使用者切換地區後,可以取得並顯示該地區的天氣資訊
在這個單元中要來讓使用這能夠實際更換顯示天氣資訊的地區,如下圖所示,使用者在選擇區域並點選儲存後,回到天氣資訊頁面就可以看到該地區即時的天氣資訊:

整個流程會像這樣,在這整個專案中,大部分的資料狀態都是保存在最上層的 App 元件中,透過 props 的方式傳遞給其他需要的元件。因此這裡我們會維持這樣的原則,在 App 元件中,會保存要顯示的天氣資訊的地區,接著讓使用者可以在 WeatherSetting 頁面中去修改地區,但實際上是更新 App 中地區的資料狀態。
在 App 中定義目前地區#
由於實際上發送 API 請求,拉取資料的動作(useWeatherAPI)是在 App 元件中,因此可以在 App 元件中透過 useState 定義當前要拉取天氣資料的地區,並且把可以修改天氣地區的方法透過 props 傳到 WeatherSetting 元件中,讓該元件可以修改 WeatherApp 內當前地區的資料。
- 使用
useState定義當前要拉取天氣資訊的地區(currentCity),預設值先定為「臺北市」
- 透過
import匯入剛剛在utils.js中定義好的findLocation方法 - 根據
currentCity來找出對應到不同 API 時使用的地區名稱,找到的地區取名為currentLocation
透過 currentLocation 就可以取得所有 API 需要使用到的 locationName,以臺北市為例,currentLocation 會是:
- 這裡的
findLocation這行也同樣可以用上useMemo的概念,只要currentCity沒有改變的情況下,即使元件重新轉譯,也不需要重新取值:
- 在
useWeatherAPI和getMoment的參數中,就可以更改為使用currentLocation取得的地區資料:
- 在 App 元件中原本使用的
LOCATION_NAME和LOCATION_NAME_FORECAST這兩個常數了,因為可以透過currentLocation取得,因此可以把這兩個常數移除。
透過 React Developer Tools 改變 currentLocation 的資料狀態#
現在我們可以透過 React Developer Tools ,從開發者工具中 State 的地方,把「臺北市」改成其他縣市,看看左側的畫面是否會連帶改變:

這裡你會發現天氣卡片的地區顯示有些不太正確,這是因為原本的 weatherElement.locationName 會是局屬氣象站的名稱,而不是縣市名稱。
App 元件#
我們可以把 cityName 透過 props 傳入 WeatherCard 元件加以顯示:
WeatherCard 元件#
接著在 WeatherCard 元件中,可以直接把 cityName 從 props 取出後顯示。另外現在用不到原本從 weatherElement 中取出的locationName(局屬氣象站),可以一併移除:
現在天氣卡片就會正確顯示縣市名稱,而不是局屬氣象站的名稱!
讓使用者從設定頁改變地區資訊#
接著,和切換頁面(handleCurrentPageChange)的方式一樣,把 handleCurrentCityChange 方法透過 props 傳入,讓 WeatherSetting 可以去修改 currentCity,以更新要拉取天氣資料的地區,如下圖所示:
圖一:

App 元件#
WeatherSetting 元件#
- 從 props 中取出
cityName和handleCurrentCityChange - 把
cityName當成locationName這個 state 的預設值,因為<input value={locationName}>,因此當使用者一進到此頁面時,地區的表單欄位就會是使用者當前的地區
- 接著在原本的
handleSave中,當使用者點擊儲存時,把使用者選擇的地區透過handleCurrentCityChange來更新 App 元件中currentCity的資料狀態,同時透過handleCurrentPageChange把使用者的頁面切換回天氣資訊頁(WeatherCard):
太棒了!現在你可以試著在設定頁面中切換地區,在按下儲存後,天氣卡片的所拉取地區也會連帶更改。
換你了!讓使用者可以自行設定地區#
在這個單元中,我們幾乎完成了所有「臺灣好天氣」的功能,現在使用者可以在設定頁面將地區切換成自己所在的地區,取得該地區的天氣資訊和降雨機率。現在要請你試著實作這個功能,你可以參考下面的步驟加以完成:
- 在 App 元件中,透過
useState取得currentCity和setCurrentCity,先以一個縣市(例如,高雄市)當作預設值。 - 透過
findLocation這個方法,將currentCity轉換成各個 API 對應需要使用的locationName -
findLocation這個方法,一樣可以透過useMemo這個方法,減少不必要的重複運算 - 取得各個 API 適用的 locationName 後,分別以參數的方式帶入
getMoment(得知目前是白天或晚上的方法)以及useWeatherAPI(取得天氣資訊的 Custom Hook) - 將
findLocation後取得的cityName以 props 的方式傳入WeatherCard元件中,以顯示正確的縣市名稱 - 將
setCurrentCity的方法先包成handleCurrentCityChange這個函式,再從 App 元件傳入WeatherSetting元件中,讓使用者可以在設定頁修改顯示的地區 - 在 WeatherSetting 元件中,當使用者點擊儲存後,透過
handleCurrentCityChange更新 App 元件中currentCity的資料狀態,並透過handleCurrentPageChange切換回天氣資訊頁
現在,你可以自由切換地區了!但現在還剩下最後一個功能需要完成,因為目前沒有把使用者選擇的地區資訊保存下來,因此只要使用者重新整理頁面,地區就會切換為一開始的 currentCity 的預設值。在下一個單元中,我們要來把使用者選擇的地區資訊保存下來。
本單元相關之網頁連結、完整程式碼與程式碼變更部分可於 select-location-in-weather-setting 分支檢視:https://github.com/pjchender/learn-react-from-hook-realtime-weather-app/tree/select-location-in-weather-setting

圖一的文字內容:
App
- handleCurrentCityChange
- currentCity
WeatherSetting, WeatherCard
<WeatherSetting handleCurrentCityChange={handleCurrentCityChange} />, handleCurrentCityChange(“台南市”)
- 將更新 currentCity 的方法傳入子元件中
- 透過該方法更新 app 中的 currentCity 資料狀態