Untitled

mail@pastecode.io avatar
unknown
javascript
3 years ago
3.3 kB
7
Indexable
Never
/**
 * Здравствуйте!
 *
 * Найдите пожалуйста ошибки коде,
 * а также, по возможности, оптимизируйте время рендера (не трогая ExpensiveTree).
 *
 * Пришлите ссылку с исправленным кодом (Gist, CodeSandbox, CodePen, JSBin, PasteBin, etc)
 */

 import React, { useEffect, useState } from "react";

 type Props = {
   todos?: TodoItem[];
 };
 
 type TodoItem = {
   id: string | number;
   title: string;
   isDone?: boolean;
 };
 
 const App: React.FC<Props> = props => {
   const [todos, setTodos] = useState<TodoItem[]>(props.todos || []);
   const [filter, setFilter] = useState<"all" | "undone">("all");
   const [doneCount, setDoneCount] = useState(0);
 
   useEffect(() => {
     if (props.todos?.length) {
       setFilter("all");
     }
   }, [props.todos]);
 
   const addTodo = (title?: string) => {
     if (!title) {
       title = prompt("What to do?") || undefined;
     }
 
     if (title) {
       setTodos(
         todos.concat({
           id: +Date.now(),
           title
         })
       );
     }
   };
 
   const markAsDone = (todo: TodoItem) => {
     const index = todos.findIndex(item => item.id === todo.id);
 
     if (index >= 0) {
       const newTodos = [...todos];
       newTodos.splice(index, 1, { ...todo, isDone: true });
       setTodos(newTodos);
     }
     setDoneCount(doneCount + 1);
   };
 
   const markAsUndone = (todo: TodoItem) => {
     const index = todos.findIndex(item => item.id === todo.id);
 
     if (index >= 0) {
       const newTodos = [...todos];
       newTodos.splice(index, 1, { ...todo, isDone: false });
       setTodos(newTodos);
     }
 
     setDoneCount(doneCount - 1);
   };
 
   const deleteTodo = (todo: TodoItem) => {
     const index = todos.findIndex(item => item.id === todo.id);
 
     if (index >= 0) {
       const newTodos = [...todos];
       newTodos.splice(index, 1);
       setTodos(newTodos);
     }
     if (todo.isDone) {
       setDoneCount(doneCount - 1);
     }
   };
 
   const onFilterButtonClick = () => {
     setFilter(filter === "all" ? "undone" : "all");
   };
 
   return (
     <div>
       <p>{`${doneCount} / ${todos.length}`}</p>
       <ul>
         {todos
           .filter(todo => (filter === "undone" ? !todo.isDone : true))
           .map(todo => (
             <li key={`${todo.id}`}>
               <p>{`${todo.isDone ? "✅ " : ""}${todo.title}`}</p>
               <button
                 onClick={() => {
                   todo.isDone ? markAsUndone(todo) : markAsDone(todo);
                 }}
               >
                 {todo.isDone ? "Undone" : "Done"}
               </button>
               <button onClick={() => deleteTodo(todo)}>{"Delete"}</button>
             </li>
           ))}
       </ul>
       <button onClick={() => addTodo()}>{"Add"}</button>
       <button onClick={() => onFilterButtonClick()}>
         {`Show ${filter === "all" ? "undone" : "all"} todos`}
       </button>
       <ExpensiveTree />
     </div>
   );
 };
 
 function ExpensiveTree() {
   const now = performance.now();
 
   while (performance.now() - now < 1000) {
     // Artificial delay -- do nothing for 1000ms
   }
 
   return null;
 }
 
 export default App;