iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 30
1
Modern Web

使用 React 製作簡易專案管理網站:從基礎到實戰系列 第 30

[Day 30] React 攻城戰 - 顯示卡片

  • 分享至 

  • xImage
  •  

顯示卡片

我們要將 useReducer 中看板的 state 顯示出來。首先在 src/components 資料夾中新增 Card 資料夾,然後在 Card 資料夾底下新增名稱為 Card.js 的檔案以及 Card.module.scss 的樣式檔案:

import React from "react";

import styles from "./Card.module.scss";

const Card = props => {
  return (
    <div className={styles.card}>
      {props.value}
    </div>
  );
};

export default Card;
.card {
  border-radius: 4px;
  background-color: white;
  box-shadow: 1px 1px 1px gray;
  margin: 4px 0;
  padding: 8px;
  cursor: pointer;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

其中先準備好從 props 中取得卡片的內容 value 並且顯示出來。

建好 Card 元件之後,我們就可以在 Board 元件中來使用它,並且傳入看卡片內容:

import React from "react";
import styles from "./Board.module.scss";

// 引用 Card 元件
import Card from "../Card/Card";

const Board = props => {
  const [isEditingName, setIsEditingName] = React.useState(false);
  const [isAddingCard, setIsAddingCard] = React.useState(false);
  const [inputValue, setInputValue] = React.useState("");

  return (
    <div className={styles.board}>
      <button
        className={styles.closeButton}
        onClick={() => {
          props.dispatch({
            type: "REMOVE_BOARD",
            payload: {
              boardId: props.id
            }
          });
        }}
      >
        x
      </button>
      {isEditingName ? (
        <input
          autoFocus
          value={props.name}
          className={styles.editNameInput}
          onChange={e => {
            dispatch({
              type: "CHANGE_BOARD_NAME",
              payload: {
                boardId: props.id,
                boardName: e.target.value
              }
            });
          }}
          onKeyPress={e => {
            if (e.key === "Enter") {
              setIsEditingName(false);
            }
          }}
        />
      ) : (
        <h2
          className={styles.name}
          onClick={() => setIsEditingName(true)}
        >
          {props.name}
        </h2>
      )}
      {/* 從 props 取得 cardIds 和 cardsById 並且使用 Card 元件 */}
      {props.cardIds.map((id, index) => (
        <Card
          key={id}
          value={props.cardsById[id]}
      ))}
      {isAddingCard ? (
        <input
          className={styles.addCardInput}
          autoFocus
          value={inputValue}
          onChange={e => setInputValue(e.target.value)}
          onKeyPress={e => {
            if (e.key === "Enter") {
              dispatch({
                type: "ADD_CARD",
                payload: {
                  boardId: props.id,
                  cardValue: inputValue.trim()
                }
              });
              setInputValue("");
              setIsAddingCard(false);
            }
          }}
        />
      ) : (
        <button
          className={styles.addCardButton}
          onClick={() => setIsAddingCard(true)}
        >
          +新增卡片
        </button>
      )}
    </div>
  );
};

在 App 元件中使用 Board 元件要多傳入 cardIds 和 cardsById 兩個 props:

<Board
  key={id}
  name={state.boards.byId[id].name}
  // 多傳入 cardIds 和 cardsById
  cardIds={state.boards.byId[id].cardIds}
  cardsById={state.cards.byId}
/>

成果畫面

系列文結語

礙於篇幅受限,製作簡易專案管理網站的進度就到這邊,剩下的功能:改變看板順序、改變卡片順序、刪除卡片等需要結合 HTML Drag & Drop API,就留給讀者們自行到 CodeSandbox 摸索囉!

歡迎讀者們訂閱分享,也可以在文章下方留下留言或是傳站內簡訊給我喔!


上一篇
[Day 29] React 攻城戰 - 加入新增卡片功能
系列文
使用 React 製作簡易專案管理網站:從基礎到實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
阿展展展
iT邦好手 1 級 ‧ 2020-01-17 05:32:03

恭喜完賽/images/emoticon/emoticon42.gif

我要留言

立即登入留言