简体   繁体   中英

How can I pass my Todo component Data into my Todolist component using React hooks?

Here is a link https://codesandbox.io/s/fast-architecture-45u4m?file=/src/Todo.js

I added comments showing which code I am trying to move into a separate component.

So I have this todo app and the original code has all of my functions and logic in one component called TodoList.js

I'm trying to refactor my code, so that all the logic for the todo is in a separate component called Todo.js

Here is what the code looks like

 <>
      {todos.map(todo => (
        <div className='todo-row'>
          <div
            key={todo.id}
            className={todo.isComplete ? 'complete' : ''}
            key={todo.id}
            onClick={() => completeTodo(todo.id)}
          >
            {todo.text}
          </div>
          <FaWindowClose onClick={() => removeTodo(todo.id)} />
        </div>
      ))}
    </>

So I have this TodoList.js component with all of my state and functions, but when I tried to remove my todo code, I can't seem to figure out how to refactor it, so that the same data still gets passed in and I am able to use all of my functions again

      function TodoList() {
        const [todos, setTodos] = useState([]);

        const addTodo = todo => {
          if (!todo.text || /^\s*$/.test(todo.text)) {
            return;
          }

          const newTodos = [todo, ...todos];

          setTodos(newTodos);
          console.log(newTodos);
        };

        const removeTodo = id => {
          const removedArr = [...todos].filter(todoId => todoId.id !== id);

          setTodos(removedArr);
        };

        const completeTodo = id => {
          let updatedTodos = todos.map(todo => {
            if (todo.id === id) {
              todo.isComplete = !todo.isComplete;
            }
            return todo;
          });
          setTodos(updatedTodos);
        };

        return (
          <>
            <TodoForm onSubmit={addTodo} />
            <Todo />
          </>
        );
      }

      export default TodoList;

Originally, I replaced the component <Todo /> with the code I showed above in the first block. But now I wanna move all of that code into it's own component called Todo.js and then pass it in from there, but I'm running into errors because I have all my functions and state logic inside of the TodoList.js component

You can pass data and required functions to Todo component through props from TodoList component and Todo component should represent only on Todo item as per name so map should stay in TodoList component so after changes

TodoList.js

  function TodoList() {
    const [todos, setTodos] = useState([]);

    const addTodo = todo => {
      if (!todo.text || /^\s*$/.test(todo.text)) {
        return;
      }

      const newTodos = [todo, ...todos];

      setTodos(newTodos);
      console.log(newTodos);
    };

    const removeTodo = id => {
      const removedArr = [...todos].filter(todoId => todoId.id !== id);

      setTodos(removedArr);
    };

    const completeTodo = id => {
      let updatedTodos = todos.map(todo => {
        if (todo.id === id) {
          todo.isComplete = !todo.isComplete;
        }
        return todo;
      });
      setTodos(updatedTodos);
    };

    return (
      <>
        <TodoForm onSubmit={addTodo} />
        {
             todos.map(todo => <Todo to do = {todo} removeTodo={removeTodo} completeTodo={completeTodo}/>)
        }
      </>
    );
  }

  export default TodoList;

And Todo.js

const {todo} = props;
return (
    <div className='todo-row'>
      <div
        key={todo.id}
        className={todo.isComplete ? 'complete' : ''}
        key={todo.id}
        onClick={() => props.completeTodo(todo.id)}
      >
        {todo.text}
      </div>
      <FaWindowClose onClick={() => props.removeTodo(todo.id)} />
    </div>
);
 

As per your sandbox . You just need to pass Props:

Todo.js

// I want to move this code into this component
import React from "react";

import { FaWindowClose } from "react-icons/fa";

const Todo = ({ todos, completeTodo, removeTodo }) => {
  return todos.map((todo) => (
    <div className="todo-row">
      <div
        key={todo.id}
        className={todo.isComplete ? "complete" : ""}
        onClick={() => completeTodo(todo.id)}
      >
        {todo.text}
      </div>
      <FaWindowClose onClick={() => removeTodo(todo.id)} />
    </div>
  ));
};

export default Todo;


TodoList.js

import React, { useState } from "react";
import TodoForm from "./TodoForm";
import Todo from "./Todo";
import { FaWindowClose } from "react-icons/fa";

function TodoList({ onClick }) {
  const [todos, setTodos] = useState([]);

  const addTodo = (todo) => {
    if (!todo.text || /^\s*$/.test(todo.text)) {
      return;
    }

    const newTodos = [todo, ...todos];

    setTodos(newTodos);
    console.log(newTodos);
  };

  const removeTodo = (id) => {
    const removedArr = [...todos].filter((todoId) => todoId.id !== id);

    setTodos(removedArr);
  };

  const completeTodo = (id) => {
    let updatedTodos = todos.map((todo) => {
      if (todo.id === id) {
        todo.isComplete = !todo.isComplete;
      }
      return todo;
    });
    setTodos(updatedTodos);
  };

  return (
    <>
      <TodoForm onSubmit={addTodo} />
      {/* I want to move this code below into a new component called Todo.js */}
      <Todo todos={todos} completeTodo={completeTodo} removeTodo={removeTodo} />
    </>
  );
}

export default TodoList;

Here is the demo : https://codesandbox.io/s/nostalgic-silence-idm21?file=/src/TodoList.js:0-1039

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM