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 資料狀態