admin管理员组

文章数量:1287632

I’m building a simple To-Do List in React with Tailwind CSS. The issue I’m facing is that when I add multiple tasks, the list grows beyond the given card and overflows out of it instead of staying inside with a scrollbar.

Here’s my Card component:

"use client";
import React, { useState } from "react";
import List from "./List";

interface Task {
  name: string;
  status?: boolean;
}

const Card = () => {
  const [todos, setTodos] = useState<Task[]>([]);
  const [taskName, setTaskName] = useState<string>("");

  const addTask = () => {
    if (!taskName.trim()) return; // Prevent empty tasks
    setTodos([...todos, { name: taskName, status: false }]);
    setTaskName(""); // Reset input field after adding
  };

  const onDelete = (name: string) => {
    setTodos(todos.filter((todo) => todo.name !== name));
  };

  const onChecked = (name: string) => {
    setTodos(
      todos.map((todo) =>
        todo.name === name ? { ...todo, status: !todo.status } : todo
      )
    );
  };

  return (
    <div className="py-5 px-7 pb-5 shadow-xl w-max flex flex-col justify-center items-center rounded-lg bg-white h-[75%]">
      <h1 className="text-3xl font-extrabold text-gray-800">To-Do List</h1>

      <div className="flex mt-5 gap-3 justify-center items-center w-full">
        <input
          type="text"
          placeholder="Enter Task"
          value={taskName}
          onChange={(e) => setTaskName(e.target.value)}
          className="text-lg rounded-xl border border-gray-300 py-2 px-3 focus:outline-none focus:ring-2 focus:ring-blue-500 w-64"
        />
        <button
          className="bg-black text-white px-4 py-2 rounded-xl hover:bg-gray-800 transition duration-200"
          onClick={addTask}
        >
          <h1 className="text-lg font-bold">Add</h1>
        </button>
      </div>

      {/* Rendering List Component */}
      <List todos={todos} onDelete={onDelete} onChecked={onChecked} />
    </div>
  );
};

export default Card;
import React, { useEffect } from 'react';

interface Data {
  name: string;
  status?: boolean;
}

interface ListProps {
  todos: Data[];
  onDelete:  (name: string) => void;
  onChecked: (name: string) => void;
}

const List: React.FC<ListProps> = ({ todos, onDelete, onChecked }) => {

  useEffect(() => {
    console.log(todos);
  }, [todos]);

  return (
    <div className="flex flex-col justify-start items-center w-full mt-10 gap-3">
  {todos.map((todo, index) => (
    <div
      key={index}
      className="flex justify-between items-center w-full bg-white shadow-md rounded-lg px-4 py-3 border border-gray-300"
    >
      <input
        type="checkbox"
        checked={todo.status}
        onChange={() => onChecked(todo.name)}
        className="w-5 h-5 text-blue-500 accent-blue-500 cursor-pointer"
      />
      <p className={`text-lg ${todo.status ? "line-through text-gray-500" : "text-black"}`}>
        {todo.name}
      </p>
      <button
        onClick={() => onDelete(todo.name)}
        className="bg-red-500 text-white px-3 py-1 rounded-md hover:bg-red-600 transition duration-200"
      >
        Delete
      </button>
    </div>
  ))}
</div>
  );
};

export default List;

this is list component which is rendered under card component.

I’m building a simple To-Do List in React with Tailwind CSS. The issue I’m facing is that when I add multiple tasks, the list grows beyond the given card and overflows out of it instead of staying inside with a scrollbar.

Here’s my Card component:

"use client";
import React, { useState } from "react";
import List from "./List";

interface Task {
  name: string;
  status?: boolean;
}

const Card = () => {
  const [todos, setTodos] = useState<Task[]>([]);
  const [taskName, setTaskName] = useState<string>("");

  const addTask = () => {
    if (!taskName.trim()) return; // Prevent empty tasks
    setTodos([...todos, { name: taskName, status: false }]);
    setTaskName(""); // Reset input field after adding
  };

  const onDelete = (name: string) => {
    setTodos(todos.filter((todo) => todo.name !== name));
  };

  const onChecked = (name: string) => {
    setTodos(
      todos.map((todo) =>
        todo.name === name ? { ...todo, status: !todo.status } : todo
      )
    );
  };

  return (
    <div className="py-5 px-7 pb-5 shadow-xl w-max flex flex-col justify-center items-center rounded-lg bg-white h-[75%]">
      <h1 className="text-3xl font-extrabold text-gray-800">To-Do List</h1>

      <div className="flex mt-5 gap-3 justify-center items-center w-full">
        <input
          type="text"
          placeholder="Enter Task"
          value={taskName}
          onChange={(e) => setTaskName(e.target.value)}
          className="text-lg rounded-xl border border-gray-300 py-2 px-3 focus:outline-none focus:ring-2 focus:ring-blue-500 w-64"
        />
        <button
          className="bg-black text-white px-4 py-2 rounded-xl hover:bg-gray-800 transition duration-200"
          onClick={addTask}
        >
          <h1 className="text-lg font-bold">Add</h1>
        </button>
      </div>

      {/* Rendering List Component */}
      <List todos={todos} onDelete={onDelete} onChecked={onChecked} />
    </div>
  );
};

export default Card;
import React, { useEffect } from 'react';

interface Data {
  name: string;
  status?: boolean;
}

interface ListProps {
  todos: Data[];
  onDelete:  (name: string) => void;
  onChecked: (name: string) => void;
}

const List: React.FC<ListProps> = ({ todos, onDelete, onChecked }) => {

  useEffect(() => {
    console.log(todos);
  }, [todos]);

  return (
    <div className="flex flex-col justify-start items-center w-full mt-10 gap-3">
  {todos.map((todo, index) => (
    <div
      key={index}
      className="flex justify-between items-center w-full bg-white shadow-md rounded-lg px-4 py-3 border border-gray-300"
    >
      <input
        type="checkbox"
        checked={todo.status}
        onChange={() => onChecked(todo.name)}
        className="w-5 h-5 text-blue-500 accent-blue-500 cursor-pointer"
      />
      <p className={`text-lg ${todo.status ? "line-through text-gray-500" : "text-black"}`}>
        {todo.name}
      </p>
      <button
        onClick={() => onDelete(todo.name)}
        className="bg-red-500 text-white px-3 py-1 rounded-md hover:bg-red-600 transition duration-200"
      >
        Delete
      </button>
    </div>
  ))}
</div>
  );
};

export default List;

this is list component which is rendered under card component.

Share Improve this question asked Feb 23 at 8:52 Yash MakesarYash Makesar 11 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

You haven't specified where you'd like the scroll to be. However, if you'd like it for the list only, you can add min-height: 0 and overflow-y: auto to the List root <div> element.

<script src="https://unpkg/@tailwindcss/[email protected]"></script>

<div id="app"></div>

<script src="https://unpkg/@babel/[email protected]"></script>
<script type="text/babel" data-type="module">
  import React, { useState, useEffect } from "https://esm.sh/[email protected]";
  import ReactDOM from "https://esm.sh/[email protected]/client";
  
  const List = ({ todos, onDelete, onChecked }) => {

  useEffect(() => {
    console.log(todos);
  }, [todos]);

  return (
    <div className="flex flex-col justify-start items-center w-full mt-10 gap-3 min-h-0 overflow-y-auto">
  {todos.map((todo, index) => (
    <div
      key={index}
      className="flex justify-between items-center w-full bg-white shadow-md rounded-lg px-4 py-3 border border-gray-300"
    >
      <input
        type="checkbox"
        checked={todo.status}
        onChange={() => onChecked(todo.name)}
        className="w-5 h-5 text-blue-500 accent-blue-500 cursor-pointer"
      />
      <p className={`text-lg ${todo.status ? "line-through text-gray-500" : "text-black"}`}>
        {todo.name}
      </p>
      <button
        onClick={() => onDelete(todo.name)}
        className="bg-red-500 text-white px-3 py-1 rounded-md hover:bg-red-600 transition duration-200"
      >
        Delete
      </button>
    </div>
  ))}
</div>
  );
};

  const Card = () => {
    const [todos, setTodos] = useState([]);
    const [taskName, setTaskName] = useState("");

    const addTask = () => {
      if (!taskName.trim()) return; // Prevent empty tasks
      setTodos([...todos, { name: taskName, status: false }]);
      setTaskName(""); // Reset input field after adding
    };

    const onDelete = (name: string) => {
      setTodos(todos.filter((todo) => todo.name !== name));
    };

    const onChecked = (name: string) => {
      setTodos(
        todos.map((todo) =>
          todo.name === name ? { ...todo, status: !todo.status } : todo
        )
      );
    };

    return (
      <div className="py-5 px-7 pb-5 shadow-xl w-max flex flex-col justify-center items-center rounded-lg bg-white h-[75%]">
        <h1 className="text-3xl font-extrabold text-gray-800">To-Do List</h1>

        <div className="flex mt-5 gap-3 justify-center items-center w-full">
          <input
            type="text"
            placeholder="Enter Task"
            value={taskName}
            onChange={(e) => setTaskName(e.target.value)}
            className="text-lg rounded-xl border border-gray-300 py-2 px-3 focus:outline-none focus:ring-2 focus:ring-blue-500 w-64"
          />
          <button
            className="bg-black text-white px-4 py-2 rounded-xl hover:bg-gray-800 transition duration-200"
            onClick={addTask}
          >
            <h1 className="text-lg font-bold">Add</h1>
          </button>
        </div>

        {/* Rendering List Component */}
        <List todos={todos} onDelete={onDelete} onChecked={onChecked} />
      </div>
    );
  }

  ReactDOM.createRoot(document.getElementById('app')).render(
    <div className="h-screen">
      <Card/>
    </div>
  );
</script>

min-height: 0 overrides the default min-height: min-content that is applied to children in a vertical flex layout.

overflow-y: auto allows the scrolling.

本文标签: typescriptReact ToDo List Overflows Container Instead of ScrollingStack Overflow