iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 24
0
Modern Web

React 30天系列 第 24

Day 24-透過URL Parameters處理News內頁

前情提要:昨天把News API的資料都串好了,今天來處理內頁吧!

目標說明:

  1. 如果有內文的話可以連到新聞內頁,沒有的話則另開新分頁打開來源URL
  2. 使用URL Parameters取得該則新聞index
  3. 點擊新聞標題後可以看到新聞圖片和內文
  4. 新聞內頁有back按鈕返回上一頁

會有第1點這麼奇怪的處理方式是因為從response可以看出,不是每則新聞都有content,但又想做內頁,所以就把有content的新聞拉出來做內頁,沒有的話就直接導引至原始新聞頁。
https://ithelp.ithome.com.tw/upload/images/20181031/20111595xDb8U8XU6m.png

第一步我們先在NewsListItem加上content的判斷吧!
articles是儲存在store內的新聞資料,這邊有再新增一個ItemAnchor component處理anchor element,判斷acticles內是否有content,有的話使用react router <Link> component,沒有的話則直接取url開新分頁至原始新聞。
這邊使用Composition(組合)的方式將anchor和news title結合。
可以看到Link to的位置設定在${pathname}/${index},因為新聞沒有id,所以就簡單的使用index當作是判斷哪則新聞的依據。

const ItemAnchor = ({ news, pathname, index, children, className }) => {
  return news.content ? (
    <Link to={`${pathname}/${index}`} className={className}>{children}</Link>
  ) : (
    <a href={news.url} target="_blank" className={className}>
      <span className="news-item-anchor-text">{children}</span>
      <FontAwesomeIcon icon={faExternalLinkAlt} color="#999" size="xs" />
    </a>
  );
};

const NewsListItem = ({ articles, pathname }) =>
  articles.map((news, index) => (
    <li key={index} className="news-item">
      <ItemAnchor news={news} pathname={pathname} index={index}  className="news-item-anchor">
        {news.title}
      </ItemAnchor>
    </li>
  )
);

在處理anchor element這邊我簡單做個區分,如果是連外的新聞Link,有再加個icon示意,所以可以看到下圖慘烈的狀況,幾乎每則新聞都沒有content ಠ_ಠ
https://ithelp.ithome.com.tw/upload/images/20181031/20111595FzHEvnSL2t.png

接著再回到router.js新增新聞內頁的Route設定,如果news後面有帶參數的話統一使用NewsDetail component顯示內容,而這個URL參數就是index。

const RootRouter = () => {
  return (
    <Router>
      <Layout>
        <Switch>
          // ...
          <Route path="/news/:index" component={NewsDetail} />
          // ...
        </Switch>
      </Layout>
    </Router>
  );
};

在NewsDetail透過connect取得state資料,之前的使用方法大多只用到第一個參數取state,今天終於可以用到第二個參數取得其它props,透過props可以收到react router的history、location和match等資訊。
要取得URL parameters的話會需要使用match object,match object內的資訊提供<Route path>如何匹配URL,其中包含以下屬性:

  1. params - (object) 從與URL相關的動態路徑片段解析Key/value
  2. isExact - (boolean) 為true時,整個URL都要匹配
  3. path - (string) 用來匹配的路徑,用於建立巢狀<Route>
  4. url - (string) URL匹配的部分,用於建立巢狀<Link>

實際得到的內容如下:
https://ithelp.ithome.com.tw/upload/images/20181031/20111595lQWuM27YNH.png

今天需要借助params的index值取得該筆新聞資料,接著將該筆資料命名為newsDetail作為props傳入component內使用。
因為在新聞內頁要能返回上個history stack,使用了history內的goBack function,而history.goBack()即等於history.go(-1)。順帶一提如果是下一頁的話則使用history.goForward(),這個method也等於執行history.go(1),詳細內容可參閱react-router API history

NewsDatail.js

// ...
const BackButton = ({ goBack }) => (
  <span className="back-btn" onClick={goBack}>
    <FontAwesomeIcon
      icon={faArrowCircleLeft}
      color="rgba(0,0,0,.3)"
      size="4x"
    />
  </span>
);

const NewsDetail = ({ newsDetail, history }) => {
  return (
    <main className="main news-detail">
      <BackButton goBack={history.goBack} />
      <NewsDetailContent newsDetail={newsDetail} />
    </main>
  );
};

const mapStateToProps = ({ news: { articles } }, ownProps) => {
  const { index } = ownProps.match.params;
  return {
    newsDetail: articles[index]
  };
};

export default connect(mapStateToProps)(NewsDetail);

以為歷經沒content的新聞已經是失策了,沒想到其實就算有content也不是全文XD
沒關係沒關係小練習而已,大家別介意,透過URL parameters處理的內頁畫面如下
Imgur

不知不覺變成隨手小練習,真心覺得愧疚,照理來說router的功能應該要可以直接透過Route取得對應的component顯示內容,但因為是透過News API取得資料,所以reload後資料就沒了哈哈哈哈......,這時候大概只能做Redirect返回news,重新取得News資料。
github傳送門

第24天了,覺得很多細節還沒有好好釐清,再繼續好好加油吧!

題外話~
今天我獲得了人生中第一次在台北市區開車的經驗~!
最大的感想是車位真的很難找!


上一篇
Day 23-使用redux-thunk處理News API
下一篇
Day 25-你好,Hello,こんにちは(react-intl初認識)
系列文
React 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言