感覺在每個框架都得學的觀念。
簡述
這邊會拿我做的垃圾 Todo list 來當範例:
它的結構長這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function App() { const [todos, setTodos] = useState([ { id: 0, content: '吃飯', isDone: true }, { id: 1, content: '寫文章', isDone: false }, { id: 2, content: '寫程式', isDone: false }, ])
return ( <div style={rootStyle}> <TodoHeader addTodo={addTodo}></TodoHeader> {todos.map(todo => <TodoItem key={todo.id} todo={todo}</TodoItem>)} </div> ); }
|
如果懶得看 code 的話,那就參考下面:
- App
- TodoHeader(上面的輸入區塊)
- TodoItem(下面的 Todo 列表)
現在的問題是,「如果 Todo 的狀態是儲存在 App 上,那我按下刪除按鈕時要怎麼去改到 App 的 State?」
其實解法還蠻直覺的,只是要稍微想一下就是了。
既然我們可以透過 props
把東西傳到子元件上,那我直接傳一個 function 不就好了嗎?
像是這樣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| function App() { const [todos, setTodos] = useState([ { id: 0, content: '吃飯', isDone: true }, { id: 1, content: '寫文章', isDone: false }, { id: 2, content: '寫程式', isDone: false }, ]) const handleRemoveTodo = id => { setTodos(todos.filter(todo => todo.id !== id)) } return ( <div style={rootStyle}> // 透過 props 傳給子層 <TodoHeader handleRemoveTodo={handleRemoveTodo}></TodoHeader> {todos.map(todo => <TodoItem key={todo.id} todo={todo}</TodoItem>)} </div> ); }
|
接著就可以在子層接到這個 props
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function TodoItem ({ todo, handleRemoveTodo }) {
const handleButtonClick = () => { handleRemoveTodo(Number(e.target.getAttribute('data-id'))) }
return ( <TodoItemWrapper> <TodoContent>{todo.content}</TodoContent> <TodoButtonWrapper> <GreenButton isDone={todo.isDone} data-id={todo.id} onClick={handleButtonClick}>{todo.isDone ? '已完成' : '未完成'} </GreenButton> <RedButton data-id={todo.id}>刪除</RedButton> </TodoButtonWrapper> </TodoItemWrapper> ) }
|
如此一來,就可以從子層去改變父層的 state,這就是元件之間的溝通方式,透過 props。