动手做Get your hands on it
练习跟着课文走 —— 每节课尾都有本课的练习。这一页是全部练习的总库,想集中刷题的时候来。 每个练习都写清了它来自哪一节,卡住了就回去看那一节。Practice follows the lessons — every lesson ends with the exercises for that lesson. This page is the whole library, for when you want to drill in one sitting. Each exercise names the lesson it came from, so you can go back when you stall.
练习Exercises
筛出 148 个练习 · 第 2 / 13 页。Showing 148 · page 2 / 13.你在 node-subgraph/ 里跑 npm start, 服务器起不来。报错很长,但关键信息只有两行。
You run npm start inside node-subgraph/ and the server does not come up. The error is long, but only two lines of it matter.
这是 NoteTable 真实的 props 类型。 三个空:一个数组类型、一个函数类型的参数、一个函数类型的返回值。
This is the real props type of NoteTable. Three blanks: an array type, a parameter of a function type, and the return value of a function type.
你刚 clone 好 react-notes-app,一行代码都还没写,先跑了npm run build,得到 10 个TS2582: Cannot find name 'test'。 同时 npx vitest run 显示 4 个测试全过。 最合理的判断是?
You have just cloned react-notes-app, written not one line of code, and run npm run build. You get 10 of TS2582: Cannot find name 'test'. At the same time npx vitest run shows all 4 tests passing. What is the most sensible conclusion?
两处真实的泛型用法。想清楚「TypeScript 能不能自己推断出来」。
Two real uses of generics. For each one, work out whether TypeScript can infer it on its own.
下面哪一行会在页面上显示这条笔记的标题内容?
Which line below shows the title of this note on the page?
Q1 的三个任务(Add / Delete / Edit)都要改动笔记列表。 这些逻辑主要写在哪个文件里?
All three tasks in Q1 (Add / Delete / Edit) change the note list. Which file holds most of that logic?
这是 NoteItem 真实的两个按钮。 一个要传整条笔记,一个只传 id —— 想清楚各自要传什么, 以及怎么才能「点击时才执行」。
These are the two real buttons of NoteItem. One passes the whole note, the other passes only the id. Decide what each one has to pass, and how to make it run only on the click.
添加两条笔记后刷新页面(假设有持久化),表格瞬间变空。 有时候浏览器还会卡住。先判断类型,再找病灶。
Add two notes, then reload the page (assume the notes are saved somewhere). The table goes empty at once, and sometimes the browser stops responding. First name the kind of error, then find the line that causes it.
用户点了某一行的 Delete 按钮。把下面五件事按发生顺序排好。
The user clicked the Delete button on one row. Put the five things below in the order they happen.
只给你组件外壳。按要求补出两个 state 和 handleDelete。 不要看下面的答案,先自己写。
You get only the shell of the component. Add the two states and handleDelete as described. Write it yourself before you look at the answer below.
- 用 useState 声明 notes,类型是 Note[],初始值为空数组Declare notes with useState, typed Note[], starting as an empty array
- 用 useState 声明 noteToEdit,类型是 Note | null,初始值为 nullDeclare noteToEdit with useState, typed Note | null, starting as null
- handleDelete 按 id 移除对应笔记,必须用函数式更新,不许改动原数组handleDelete removes the matching note by id, using a functional update, without changing the original array
看答案之前,先确认你已经自己动手写过一遍。看懂别人的答案和自己写出来,是两种能力。Before you open this, make sure you have written it yourself once. Following someone else's answer and producing your own are two different skills.
把 NoteForm 里 textarea 那一段补全。 三个空构成一个完整的闭环。
Fill in the textarea part of NoteForm. The three blanks together form one complete loop.
填好标题和内容,点 Add。页面明显闪了一下, 地址栏出现了 ?,表格还是空的。
Fill in a title and some content, then press Add. The page clearly blinks, a ? appears in the address bar, and the table is still empty.