今天就要來準備實作TodoList了,來看一下昨天的結果圖。
首先開一個新的專案
使用 create-react-app
建立一個 React 專案
npx create-react-app todo-app
cd todo-app
由於用到 styled-components
套件來編寫樣式
npm install styled-components
App.js
是我們的主要邏輯元件,它負責管理所有的待辦事項,並透過 useState
來更新應用程式的狀態。接著它會將資料傳遞給 TodoList
和 TodoForm
元件,讓這些元件負責渲染與互動。
import React, { useState } from 'react';
import styled, { createGlobalStyle } from 'styled-components';
import TodoList from './TodoList';
import TodoForm from './TodoForm';
const GlobalStyle = createGlobalStyle`
body {
font-family: 'Arial', sans-serif;
background-color: #f0f4f8;
margin: 0;
padding: 0;
}
`;
const Container = styled.div`
max-width: 600px;
margin: 50px auto;
padding: 20px;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
text-align: center;
`;
const Title = styled.h1`
font-size: 2.5rem;
color: #333;
margin-bottom: 20px;
`;
const App = () => {
const [todos, setTodos] = useState([
{ id: 1, text: '學習 React', completed: false },
{ id: 2, text: '完成作業', completed: false }
]);
const addTodo = (text) => {
setTodos([...todos, { id: Date.now(), text, completed: false }]);
};
const toggleComplete = (id) => {
setTodos(
todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
)
);
};
// 刪除待辦事項
const deleteTodo = id => {
setTodos(todos.filter(todo => todo.id !== id))
}
return (
<Container>
<GlobalStyle />
<Title>待辦事項清單</Title>
<TodoForm addTodo={addTodo} />
<TodoList todos={todos} toggleComplete={toggleComplete} deleteTodo={deleteTodo} />
</Container>
);
};
export default App;
TodoList
元件負責將待辦事項渲染出來,它接收 todos
陣列並根據每個待辦事項的狀態來決定是否顯示為已完成。
import React from 'react';
import Todo from './Todo';
import styled from 'styled-components';
const List = styled.ul`
list-style: none;
padding: 0;
`;
const TodoList = ({ todos, toggleComplete,deleteTodo }) => {
return (
<List>
{todos.map(todo => (
<Todo key={todo.id} todo={todo} toggleComplete={toggleComplete} deleteTodo={deleteTodo} />
))}
</List>
);
};
export default TodoList;
這個元件會接收 todo
物件與 toggleComplete
、deleteTodo
方法,並根據待辦事項的狀態來動態渲染按鈕和樣式。
import React from 'react';
import styled from 'styled-components';
const TodoItem = styled.li`
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
margin-bottom: 10px;
background-color: #f9f9f9;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
transition: background-color 0.3s ease;
text-decoration: ${(props) => (props.completed ? 'line-through' : 'none')};
&:hover {
background-color: #e6f7ff;
}
`;
const Text = styled.span`
flex: 1;
font-size: 1.2rem;
color: ${(props) => (props.completed ? '#b0b0b0' : '#333')};
`;
const Button = styled.button`
background-color: ${(props) => (props.completed ? '#52c41a' : '#1890ff')};
color: white;
border: none;
padding: 5px 10px;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s ease;
&:hover {
background-color: ${(props) => (props.completed ? '#389e0d' : '#096dd9')};
}
`;
const Todo = ({ todo, toggleComplete }) => {
return (
<TodoItem completed={todo.completed}>
<Text completed={todo.completed}>{todo.text}</Text>
<Button completed={todo.completed} onClick={() => toggleComplete(todo.id)}>
{todo.completed ? '已完成' : '完成'}
</Button>
<Button onClick={() => deleteTodo(todo.id)}>刪除</Button>
</TodoItem>
);
};
export default Todo;
TodoForm
會包含一個輸入框和按鈕,讓使用者可以新增新的待辦事項。
當使用者按下新增時,會將新的事項加入待辦列表中。
import React, { useState } from 'react';
import styled from 'styled-components';
const Form = styled.form`
display: flex;
justify-content: space-between;
margin-bottom: 20px;
`;
const Input = styled.input`
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
margin-right: 10px;
font-size: 1rem;
`;
const Button = styled.button`
background-color: #1890ff;
color: white;
border: none;
padding: 10px 15px;
border-radius: 5px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s ease;
&:hover {
background-color: #096dd9;
}
`;
const TodoForm = ({ addTodo }) => {
const [input, setInput] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (input) {
addTodo(input);
setInput('');
}
};
return (
<Form onSubmit={handleSubmit}>
<Input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="輸入待辦事項..."
/>
<Button type="submit">新增</Button>
</Form>
);
};
export default TodoForm;
完成上述的程式碼後,接下來運行 npm start
就可以看到我們的待辦事項應用程式。
也可以直接透過CodeSandbox 來線上觀看範例-Todo.js - nodebox - CodeSandbox
以上內容就是我們這次的綜合練習,複習之前的教學內容,從這專案中實作到 元件建立、props、state、事件處理、表單處理、條件渲染、列表渲染與 Styled Components,可以去檢視自己哪方便還不太熟悉。
接下來,明天將會繼續說明React的功能。
本文將會同步更新到我的部落格