7-3 實作頁面間的切換功能

本單元對應的專案分支:switch-between-pages

單元核心#

這個單元的主要目標包含:

  • 讓使用者可以直接於 UI 上切換不同頁面

在上一個單元中,讀者已經可以透過 React Developer Tools 來檢驗頁面切換的效果。在這個單元中,我們要讓使用者直接透過畫面上的按鈕點擊來達到頁面間的切換。

在 WeatherCard 元件中添加進入設定頁的按鈕#

現在你會看到畫面上變成像原本一樣,只看到天氣資訊的卡片,那麼要怎麼讓使用者切換到設定頁呢?

我們可以在 WeatherCard 元件中,新增一個齒輪的圖示,使用者可以透過點擊齒輪圖示來進到設定頁面:

Imgur

  1. 在原本的 ./src/images 中就有放了齒輪的圖示,因此可直接使用 import 載入齒輪圖示(cog.svg
// ./src/views/WeatherCard.js
// ...
import { ReactComponent as CogIcon } from './../images/cog.svg';
  1. 透過 @emotion/styled 幫齒輪添加樣式
// ./src/views/WeatherCard.js
// ...
const Cog = styled(CogIcon)`
position: absolute;
top: 30px;
right: 15px;
width: 15px;
height: 15px;
cursor: pointer;
`;
  1. 在 JSX 中使用齒輪圖示
// ./src/views/WeatherCard.js
// ...
const WeatherCard = () => {
// ...
return (
<WeatherCardWrapper>
{/* 放入齒輪圖示 */}
<Cog />
<Location>{locationName}</Location>
{/* ... */}
</WeatherCardWrapper>
);
};

現在我們的天氣資訊頁就可以看到齒輪的按鈕了:

imgur

讓子層元件可以修改父層元件的資料狀態#

現在控制顯示哪個頁面的資料狀態,是由放在 App 元件中的 currentPage 來決定,但我們希望使用者點擊 WeatherCard 的元件中的按鈕時,就可以去修改 currentPage 的資料狀態。這裡就會需要用到「讓子層元件可以修改父層元件的資料狀態」。

這個部分我們在前面實作網速單位換算器時已經提過,由於子元件並不能「直接」修改父層元件的資料,而是需要透過父元件將修改資料的方法傳遞到子元件來完成。

以這裡來說,在 App 元件中,若想要修改 currentPage 時,需要使用 setCurrentPage 這個方法;現在當我們想在子元件 WeatherCard 修改父元件 WeatherApp 的 currentPage 狀態時,做法是一樣的,只需要使用 setCurrentPage 這個方法。

那麼子層元件要如何取得 setCurrentPage 這個方法呢?還記得透過 props 一樣可以傳遞函式嗎?現在我們只需要在 App 元件中定義一個 handleCurrentPage 的函式,並在這個函式中執行 setCurrentPage 這個方法,最後將 handleCurrentPageChange 透過 props 從 App 元件傳遞到 WeatherCard 元件中,WeatherCard 就可以透過 handleCurrentPageChange 這個方法來更新 currentPage 的資料狀態了。

App 元件#

回到 App.js 中把 setCurrentPage 這個方法,包成一個 handleCurrentPageChange 的函式,接著再透過 props 把分別傳入 <WeatherCard /><WeatherSetting /> 這兩個元件中:

// ./src/App.js
const App = () => {
// ...
const [currentPage, setCurrentPage] = useState('WeatherCard');
const handleCurrentPageChange = (currentPage) => {
setCurrentPage(currentPage);
};
return (
// 將 handleCurrentPageChange 透過 props 傳進 WeatherCard 元件中
<WeatherCard
weatherElement={weatherElement}
moment={moment}
fetchData={fetchData}
handleCurrentPageChange={handleCurrentPageChange}
/>
// 將 handleCurrentPageChange 透過 props 傳進 WeatherSetting 元件中
<WeatherSetting handleCurrentPageChange={handleCurrentPageChange} />
);
};

在 WeatherCard 中呼叫 handleCurrentPageChange 方法#

接著到 WeatherCard.js 中,就可以

  1. 透過 props 取出傳入的 handleCurrentPageChange 方法
  2. 當齒輪被點擊時,透過 handleCurrentPageChangecurrentPage 改成 WeatherSetting
// ./src/views/WeatherCard.js
// STEP 1:從 props 中取出 handleCurrentPageChange
const WeatherCard = ({ weatherElement, moment, fetchData, handleCurrentPageChange }) => {
// ...
return (
{/* STEP 2:當齒輪被點擊的時候,將 currentPage 改成 WeatherSetting */}
<Cog onClick={() => handleCurrentPageChange('WeatherSetting')} />
)
}

現在當我們點擊齒輪的按鈕時,就會觸發 onClick 事件,handleCurrentPageChange 就會被呼叫到,這時候位於父元件 WeatherApp 中的 currentPage 就會被修改,同時觸發元件重新轉譯,重新轉譯後就會顯示對應到的 WeatherSetting 頁面。

在 WeatherSetting 中呼叫 handleCurrentPageChange 方法#

現在我們可以從 WeatherCard 進到 WeatherSetting 頁面,同樣只要在 WeatherSetting 元件中呼叫 handleCurrentPageChange 方法,就可以回到 WeatherCard 頁面:

  1. 從 props 中取出handleCurrentPageChange 方法
  2. 在「返回按鈕」被點擊時呼叫 handleCurrentPageChange 方法,切換顯示頁面到 WeatherCard
// ./src/views/WeatherSetting.js
// STEP 1:從 props 中取出 handleCurrentPageChange
const WeatherSetting = ({ handleCurrentPageChange }) => {
<ButtonGroup>
{/* STEP 2:呼叫 handleCurrentPageChange 方法來換頁 */}
<Back onClick={() => handleCurrentPageChange('WeatherCard')}>返回</Back>
<Save>儲存</Save>
</ButtonGroup>;
};

現在,我們就可以正常的切換頁面了。

只要簡單透過條件轉譯就可以讓使用者有切換頁面的感覺。許多前端路由的工具(例如,react-router),本質上也是透過條件轉譯的方式來切換不同頁面,但這些前端路由的工具又處理了更多事務,包含換頁的時候同時更換顯示的網址;當使用者輸入網址後,能夠去處理這個網址對應要顯示的元件為何。

換你了!實作頁面間的切換功能#

在這個單元中,整合了過去學習的幾個不同部分,像是 useState、props 的傳遞、由子元件修改父元件的資料狀態、條件轉譯的使用等等,透過這些整合,就可以實作出頁面切換的效果。現在你可以參考下面的步驟加以完成:

  • 在 WeatherCard 元件中加入齒輪按鈕
  • setCurrentPage 方法包在 handleCurrentPageChange 函式中,並透過 props 傳入 WeatherCard 和 WeatherSetting 元件
  • 在 WeatherCard 和 WeatherSetting 元件中,透過 props 將 handleCurrentPageChange 取出,並在對應的按鈕被 onClick 時進行頁面的切換

本單元相關之網頁連結、完整程式碼與程式碼變更部分可於 switch-between-pages 分支檢視:https://github.com/pjchender/learn-react-from-hook-realtime-weather-app/tree/switch-between-pages

Imgur