本系列文以製作專案為主軸,紀錄小弟學習React以及GrahQL的過程。主要是記下重點步驟以及我覺得需要記憶的部分,有覺得不明確的地方還請留言多多指教。
前回寫在KanBan裡的NavBar部件太大一串了,先抽離這個部分,之後再回來改。
在components資料夾底下製作KanBanNav.jsx
// KanBanNav.jsx
import React from "react";
import {
Navbar,
Nav,
NavDropdown,
Form,
FormControl,
Button,
} from "react-bootstrap";
export default function KanBanNav() {
return (
<Navbar expand="lg">
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Nav.Link href="#home">Home</Nav.Link>
<Nav.Link href="#link">Link</Nav.Link>
<NavDropdown title="Dropdown" id="basic-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">
Another action
</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">
Separated link
</NavDropdown.Item>
</NavDropdown>
</Nav>
<Form inline>
<FormControl type="text" placeholder="Search" className="mr-sm-2" />
<Button>Search</Button>
</Form>
</Navbar.Collapse>
</Navbar>
);
}
跟原本的KanBan基本一樣,然後回到KanBan做清理跟載入
// KanBan.jsx
import React from "react";
import KanBanNav from "./KanBanNav"; //載入
export default function KanBan() {
return (
<KanBanNav></KanBanNav> //清除掉原本的之後加上
);
}
做List會用到Todo部件,所以先做這部分。
//Todo.jsx
import React from "react";
export default function Todo() {
return <div className="todo my-1 p-1 rounded">Todo1</div>;
}
目前只簡單顯示寫死的Todo名稱,外加一些造型。
//List.jsx
import React from "react";
import Todo from "./Todo";
export default function List() {
return (
<div className="list p-2 m-1 rounded-lg">
<div className="title">List1</div>
<Todo></Todo>
<Todo></Todo>
</div>
);
}
寫死的標題之外掛上兩個Todo,後面在改寫成動態載入的。
然後掛到KanBan上
import React from "react";
import { Container, Row } from "react-bootstrap";
import KanBanNav from "./KanBanNav";
import List from "./List";
export default function KanBan() {
return (
<span>
<KanBanNav></KanBanNav>
<Container fluid className="board p-1">
<Row className="m-0">
<List></List>
<List></List>
</Row>
</Container>
</span>
);
}
用Bootstrap Grid讓List從左到右並列。
完成畫面,看到並列的List1,各帶兩個Todo1。
這邊已經有用Sass加上顏色方便辨識,關於Sass預計之後統整一篇介紹,這邊先跳過。
以上過程中的心得:
拆分部件的流程基本有兩個:
2就比較需要經驗判斷,如果是清單的構造就很好想,不過有些時候要拆多細還要根據部件的功能思考,會不會在其他地方用到? 是不是帶入新的props就能讓部件能夠重複使用?
不清楚的時候還是先用1的方式做做看,再想想有沒有需要拆、有沒有辦法拆吧。
上面部件裡的標題、名稱都是寫死的,現在要改用帶入資料的方式去動態顯示每個部件的內容。
首先建假資料:
export default function KanBan() {
const dummyData = [
{
title: "list1",
todos: [
{
name: "todo1",
finished: false,
},
{
name: "todo2",
finished: false,
},
],
},
{
title: "list2",
todos: [
{
name: "todo3",
finished: false,
},
{
name: "todo4",
finished: false,
},
],
},
];
...
}
這邊用陣列包含兩個list物件,各自有標題、包含的todo陣列,todo的名稱與是否完成的資訊。
用陣列的原因是為了方便在JSX中用迴圈的方式加載部件,下面會介紹
接著用dummyData做成state
import React, { useState } from "react"; //載入useState方法
export default function KanBan() {
const dummyData = [...];
const [lists, updateLists] = useState(dummyData); //建立state
}
useState接收dummyData作為state的初始值,回傳存取state的變數lists, 以及之後用於更新state的方法updateLists。
然後就能用迴圈的方式產生動態的List物件:
export default function KanBan() {
const dummyData = [...];
const [lists, updateLists] = useState(dummyData);
return (
<span>
<KanBanNav />
<Container fluid className="board p-1">
<Row className="m-0">
{lists.map((list, index) => (
<List key={index} {...list} /> //用展開運算子載入props
))}
</Row>
</Container>
</span>
);
}
這邊有個帶props的小技巧,如果state是個包含許多key的物件,可以用ES6的展開運算子全部帶成props。
到List裡接收props:
// List.jsx
export default function List({ title, todos }) {
return (
<div className="list p-2 m-1 rounded-lg">
<div className="title">{title}</div> //帶入標題
{todos.map((todo, index) => ( //產生todo清單
<Todo key={index} name={todo.name} />
))}
</div>
);
}
跟帶入props一樣,接收props可以利用解構賦值的方式存取,比較一下有無用解構賦值的差別:
// 直接用解構賦值
export default function List({ title, todos }) {
...
}
//載入props後再解構賦值
export default function List(props) {
const { title, todos } = props
...
}
//不用解構賦值
export default function List(props) {
const title = props.title
const todos = props.todos
...
}
當props很多的時候直接解構賦值能少寫很多行,也更直接看出這個部件需要那些props,不過要注意傳入、解構的變數名稱必須相同。
最後傳資料給Todo:
//Todo.jsx
import React from "react";
export default function Todo({ name }) {
return <div className="todo my-1 p-1 rounded">{name}</div>;
}
到目前的畫面:
可以看到清單的標題,代辦事項的名稱都根據提供的資料變更了。
到這裡基礎的清單就建好了,接著製作新增代辦事項的功能。