You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的属性,属性值才是任务数组。

正确写法(两种可选)

  1. 解构props直接取数组:
const List = ({ tasks }: { tasks: {id: string; task: string}[] }) => (
  <ul>
    {tasks.map((task) => (
      <li key={task.id}>{task.task}</li>
    ))}
  </ul>
);

这样就能直接用tasks.map,不用嵌套调用。

  1. 接收完整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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:47:46