在上一篇文章中,我們建立了一個簡單的根元件 App,並且使用 useReducer 將網站標題顯示出來:
import React from 'react';
import { reducer, initialState } from './reducer';
const App = () => {
const [state, dispatch] = React.useReducer(reducer, initialState);
return (
<div>
<h1>{state.title}</h1>
</div>
);
};
export default App;
首先我們希望在點擊標題時可以將純文字變成文字輸入框以便修改,所以需要使用 useState 建立一個 state 來控制現在是純文字還是文字輸入框的狀態 ( useState 的使用方式可以參考之前一篇文章):
import React from 'react';
import { reducer, initialState } from './reducer';
const App = () => {
const [state, dispatch] = React.useReducer(reducer, initialState);
const [isEditing, setIsEditing] = React.useState(false);
return (
<div>
{isEditing ? <input value={state.title} /> : <h1>{state.title}</h1>}
</div>
);
};
export default App;
接著將 isEditing
這個 state 在標題被點擊時設成 true,按下 Enter 時則設成 false:
import React from 'react';
import { reducer, initialState } from './reducer';
const App = () => {
const [state, dispatch] = React.useReducer(reducer, initialState);
const [isEditingTitle, setIsEditingTitle] = React.useState(false);
return (
<div>
{isEditingTitle ? (
<input
value={state.title}
// 加上 autoFocus 屬性讓文字輸入框自動出現游標
autoFocus
// 偵測按下 Enter 的事件
onKeyPress={e => {
if (e.key === "Enter") {
setIsEditingTitle(false);
}
}}
/>
) : (
<h1
// 偵測被滑鼠點擊的事件
onClick={() => setIsEditingTitle(true)}
>{state.title}</h1>
)}
</div>
);
};
export default App;
再來要讓標題有編輯的功能。偵測文字輸入框 onChange 事件,在事件發生時呼叫 dispatch 傳入 action 物件(在之前一篇文章中定義過修改標題的 action 物件):
import React from 'react';
import { reducer, initialState } from './reducer';
const App = () => {
const [state, dispatch] = React.useReducer(reducer, initialState);
const [isEditingTitle, setIsEditingTitle] = React.useState(false);
return (
<div>
{isEditingTitle ? (
<input
value={state.title}
autoFocus
onKeyPress={e => {
if (e.key === "Enter") {
setIsEditingTitle(false);
}
}}
// 偵測文字內容改變的事件
onChange={e => {
dispatch({
type: "CHANGE_TITLE",
payload: {
title: e.target.value
}
});
}}
/>
) : (
<h1
onClick={() => setIsEditingTitle(true)}
>{state.title}</h1>
)}
</div>
);
};
export default App;
接著我們希望網站標題文字可同步到網頁的標題。使用 useEffect:
import React from 'react';
import { reducer, initialState } from './reducer';
const App = () => {
const [state, dispatch] = React.useReducer(reducer, initialState);
const [isEditingTitle, setIsEditingTitle] = React.useState(false);
// 每當 state.title 變化就會更新到 document.title
React.useEffect(() => {
document.title = state.title;
}, [state.title]);
return (
<div>
{isEditingTitle ? (
<input
value={state.title}
autoFocus
onKeyPress={e => {
if (e.key === "Enter") {
setIsEditingTitle(false);
}
}}
onChange={e => {
dispatch({
type: "CHANGE_TITLE",
payload: {
title: e.target.value
}
});
}}
/>
) : (
<h1
onClick={() => setIsEditingTitle(true)}
>{state.title}</h1>
)}
</div>
);
};
export default App;
建立新增看板的元件。