鐵人賽
React
javascript
nodejs
鐵人賽第17天,週末假日,難得可以賴個床到八點半,但心裡掛念的還是今天的文章,不囉唆,立刻上工。
input
事件及reducer
的動作,做個完整的結合。input.js
中,新增一組state
,同時觸發input 的 onChange
事件,讓使用者輸入文字時,能即時更新到state
之中,這樣,當我們按下send
按鈕後,便可以直接從這個state
取出輸入的文字,並進行ADD
動作
msg
: 暫存input
欄位文字setMsg
: 存放input
文字的stateFunc
// input.js
import React, { useContext, useState } from "react";
import { ContextStore } from "./ToDoApp";
export default function Input() {
const [msg, setMsg] = useState("");
const { appReducer } = useContext(ContextStore);
const dispatch = appReducer[1];
console.log("msg", msg); //<--放一個console驗證看看
return (
<div>
<input
style={{ width: "150px" }}
onChange={(e) => setMsg(e.target.value)}
></input>
<button>{"Send"}</button>
</div>
);
}
Chrome inspector
中的console
來驗證看看,Wow...果然每輸入一個文字,都有顯示喔Reducer
,我們必須建立一個input 的 onClick事件
,並在過程中完成:
- 包裝訊息為
object
格式,如:{newEvent:msg}
// input.js
import React, { useContext, useState } from "react";
import { ContextStore } from "./ToDoApp";
// Step1: 建立一個handleAddClick事件,負責包裝訊息以符合reducer格式,並回傳dispatch完成新增訊息的動作,
function handleAddClick(newMsg, dispatch) {
const anEvent = { type: "ADD", newEvent: newMsg};
return (e)=>dispatch(anEvent); //<--為了讓handleAddClick func讓onClick使用,必須回傳一個func
}
// Step2: 我們在button新增一個onClick事件,並連結到建立一個handleAddClick事件
export default function Input() {
const [msg, setMsg] = useState("");
const { appReducer } = useContext(ContextStore);
const dispatch = appReducer[1];
console.log("msg", msg); //<--放一個console驗證看看
return (
<div>
<input
style={{ width: "150px" }}
onChange={(e) => setMsg(e.target.value)}
></input>
<button onClick={handleAddClick(msg, dispatch)}>{"Send"}</button>
</div>
);
}
toDoList
之後,我們會先運用switch
判讀action.type
確定它的動作,再到相對case
進行處理。return toDoList.push(action.newEvent)
,來看看會發生什麼事...// reducers/js
export default function reducers(toDoList, action) {
switch (action.type) {
case "ADD":
return toDoList.push(action.newEvent);
default:
return toDoList;
}
}
node
來驗證一下。我們建立一個空的Array
並利用push
來新增一個文字Hello
,你看看會回覆什麼訊息let result = [].push("hello")
console.log(result) // 1
Array.push
會回傳當下Array
的長度,故我們不能直接回傳。而且,這樣的寫法也犯了幾個錯:
React
禁止我們直接修改state
,故直接對reducer的state
做修改,是行不通的。不過,我們可以用Array解構賦值
的方式,複製一份toDoList
並做修改。- 不要直接回傳
Array.push
,應該分先push
再回傳。
// reducers.js
export default function reducers(toDoList, action) {
let newToDoList = [...toDoList];
switch (action.type) {
case "ADD":
newToDoList.push(action.newEvent); //<-- 先push
break;
default:
console.log("toDoList", toDoList); //<--直接印出舊的
break;
}
return newToDoList; //<--不管動作如何,直接回傳複製過來的newToDoList
}
}
key
上去import React, { useContext } from "react";
import { ContextStore } from "./ToDoApp";
export default function ToDoList() {
const { appReducer } = useContext(ContextStore);
const toDoList = appReducer[0];
const result = toDoList.map((e, idx) => (<p key={`cmd-${idx}`}>{e}</p>));
return result;
}
ToDoApp
中的事件處理
與reducer
做完整的連結,讓事件可以順利的新增到toDoList
之中。