React/Next中TypeScript组件Props类型定义疑问求助
Next.js + TypeScript Todo 组件问题解决
问题1:List组件props定义逻辑解析
React组件的第一个参数永远是props对象,哪怕你只传一个属性。你最初写的const List = ( tasks : {id: string; task: string}[]; )错误地把props直接当成了数组,但父组件中你是通过<List tasks={tasks} />传递的——也就是说props对象里包含一个名为tasks的属性,属性值才是任务数组。
正确写法(两种可选)
- 解构props直接取数组:
const List = ({ tasks }: { tasks: {id: string; task: string}[] }) => ( <ul> {tasks.map((task) => ( <li key={task.id}>{task.task}</li> ))} </ul> );
这样就能直接用tasks.map,不用嵌套调用。
- 接收完整props对象:
const List = (props: { tasks: {id: string; task: string}[] }) => ( <ul> {props.tasks.map((task) => ( <li key={task.id}>{task.task}</li> ))} </ul> );
通过props.tasks访问数组,逻辑更清晰。
你之前的写法之所以需要tasks.tasks.map,是因为错误地把props的类型定义成了包含tasks属性的对象,同时又把参数名取成了tasks,所以才需要两次调用。
问题2:AddTask组件props类型优化
把冗长的props类型抽成独立的类型别名或接口,既简化组件定义,又方便复用和维护。
步骤1:抽离类型
先定义通用的Task类型和AddTaskProps类型:
// 定义单个任务的类型,全局复用 type Task = { id: string; task: string; }; // AddTask组件的props类型 type AddTaskProps = { text: string; onChange: (event: React.ChangeEvent<HTMLInputElement>) => void; onAdd: () => void; };
注意:把event: any改成React.ChangeEvent<HTMLInputElement>,类型更精确,避免any带来的隐患。
步骤2:简化组件定义
const AddTask = ({ text, onChange, onAdd }: AddTaskProps) => ( <div> <input type="text" value={text} onChange={onChange} /> <button type="button" onClick={onAdd}>Add</button> </div> );
完整优化后代码
'use client'; import { useState } from "react"; import { v4 as uuidv4 } from 'uuid'; // 抽离通用Task类型 type Task = { id: string; task: string; }; const initialTasks: Task[] = [ { id: 'a', task: 'Make this app', }, { id: 'b', task: 'Do uni work', }, ]; // AddTask组件props类型 type AddTaskProps = { text: string; onChange: (event: React.ChangeEvent<HTMLInputElement>) => void; onAdd: () => void; }; export default function Home() { const [tasks, setTasks] = useState<Task[]>(initialTasks); const [text, setText] = useState(""); function addToList() { const newTask: Task = {id: uuidv4(), task: text}; setTasks([...tasks, newTask]); setText(""); } function handleChange(event: React.ChangeEvent<HTMLInputElement>) { setText(event.target.value); } return ( <div> <h1>Task Manager</h1> <p>To Do List:</p> <List tasks={tasks} /> <AddTask text={text} onChange={handleChange} onAdd={addToList} /> </div> ) } // List组件props类型复用Task const List = ({ tasks }: { tasks: Task[] }) => ( <ul> {tasks.map((task) => ( <li key={task.id}>{task.task}</li> ))} </ul> ); const AddTask = ({ text, onChange, onAdd }: AddTaskProps) => ( <div> <input type="text" value={text} onChange={onChange} /> <button type="button" onClick={onAdd}>Add</button> </div> );
内容的提问来源于stack exchange,提问作者Scott
相关产品推荐
相关产品推荐

