当我第二次换工作时,面试官要求我使用 React 创建一个待办事项列表。我认为这是一个很好的问题来测试候选人的思考和编码能力。不像刻板的写作,它更像是一个真实的面试问题。
让我们从待办事项列表的基本结构开始。
首先,我们需要一个输入字段来添加新的待办事项。
<input type="text" placeholder="new thing to be done" />
其次,我们需要一个列表来显示所有的待办事项。
const [todos, setTodos] = useState([])
然后我们需要渲染列表:
{
todos.map((todo) => <li key={todo.id}>{todo.text}</li>)
}
现在,让我们把这些组件组合在一起。
const [todos, setTodos] = useState([])
return (
<div>
<input type="text" placeholder="new thing to be done" />
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
</div>
)
现在,我们需要处理输入字段。我们可以使用表单来包装输入字段。
const inputRef = useRef(null)
<form onSubmit={handleSubmit}>
<input type="text" placeholder="new thing to be done" ref={inputRef} />
</form
为什么我们需要使用表单?因为我们想要在输入新的待办事项时防止页面刷新。当然,你也可以选择其他方式来处理这个问题。
const handleSubmit = (e) => {
e.preventDefault()
setTodos([...todos, { id: Date.now(), label: inputRef.current.value }])
inputRef.current.value = ""
}
让我们把这些组件组合在一起。
function TodoList() {
const inputRef = useRef(null)
const [todos, setTodos] = useState([])
const handleSubmit = (e) => {
e.preventDefault()
setTodos([...todos, { id: Date.now(), label: inputRef.current.value }])
inputRef.current.value = ""
}
return (
<div>
<form onSubmit={handleSubmit}>
<input type="text" placeholder="new thing to be done" ref={inputRef} />
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.label}</li>
))}
</ul>
</div>
)
}
现在我们可以添加新的待办事项。但我们需要在待办事项完成或未完成时切换它。我们应该为待办事项添加一个复选框。如果选中,则添加删除线样式。
const handleToggle = (id) => {
setTodos(
todos.map((todo) => (todo.id === id ? { ...todo, done: !todo.done } : todo))
)
}
<li key={todo.id}>
<input
type="checkbox"
checked={todo.done}
onChange={() => handleToggle(todo.id)}
/>
<label className={item.done ? "done" : "undo"}>{todo.label}</label>
</li>
之后我们还需要添加一个按钮来删除待办事项。
<li key={todo.id}>
<input
type="checkbox"
checked={todo.done}
onChange={() => handleToggle(todo.id)}
/>
{todo.label}
<button onClick={() => handleDelete(todo.id)}>x</button>
</li>
const handleDelete = (id) => {
setTodos(todos.filter((todo) => todo.id !== id))
}
就是这样。我们有了一个待办事项列表。
function TodoList() {
const inputRef = useRef(null)
const [todos, setTodos] = useState([])
const handleSubmit = (e) => {
e.preventDefault()
setTodos([
...todos,
{ id: Date.now(), label: inputRef.current.value, done: false },
])
inputRef.current.value = ""
}
const handleDelete = (id) => {
setTodos(todos.filter((todo) => todo.id !== id))
}
const handleToggle = (id) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, done: !todo.done } : todo
)
)
}
return (
<div>
<form onSubmit={handleSubmit}>
<input type="text" placeholder="new thing to be done" ref={inputRef} />
</form>
<ul>
{todos.map((todo) => (
<li key={todo.id}>
<input
type="checkbox"
checked={todo.done}
onChange={() => handleToggle(todo.id)}
/>
<label className={item.done ? "done" : "undo"}>{todo.label}</label>
<button onClick={() => handleDelete(todo.id)}>x</button>
</li>
))}
</ul>
</div>
)
}
如果你能完成上述内容,我认为你的答案基本符合要求。
但我们可以做得更好,比如:
- 我们可以将待办事项列表组件提取到一个单独的组件中。
- 我们可以通过使用 CSS 让待办事项列表组件更美观。
- 我们可以在待办事项为空时添加过滤器。
- 我们可以使用 memo 和 useCallback 来优化待办事项列表组件。
- 我们可以使用本地存储来存储待办事项列表。
- ...
如果你能完成上述内容,我认为你的答案是优秀的。试试看,祝你好运!