Home > Software engineering >  Passing a function down to child component not working
Passing a function down to child component not working

Time:07-03

first time asking something here so pardon if it's not in the right template. I'm trying to pass down a function that I created on App.js to an input component, so on a button click it changes the state in the App component and it returns errors.

App.jsx

import { useState } from "react";
import "./App.css";
import Todos from "./components/Todos";
import Input from "./components/Input";

function App() {
  const [todos, setTodos] = useState([]);
  let startingId = 1;

  function addTodo(title) {
    if (title) {
      setTodos((prev) =>
        prev.push({
          id: startingId  ,
          title: title,
          createdAt: new Date().toLocaleTimeString(),
          isComplete: false,
        })
      );
    }
    return;
  }
  return (
    <div className="app">
      <Input addTodo={addTodo} />
      <Todos todos={todos} />
    </div>
  );
}

export default App;

Input.jsx

import { useState } from "react";

function Input({ addTodo }) {
  const [todoInp, setTodoInp] = useState("");

  return (
    <div className="input mt-4 mb-5">
      <div className="input-group mb-3 container-lg">
        <input
          type="text"
          className="form-control"
          placeholder="Recipient's username"
          aria-label="Recipient's username"
          aria-describedby="button-addon2"
          value={todoInp}
          onInput={(e) => setTodoInp(e.target.value)}
        />
        <button
          className="btn btn-outline-primary"
          type="button"
          id="button-addon2"
          onClick={addTodo(todoInp)}
        >
          Add Todo
        </button>
      </div>
    </div>
  );
}

export default Input;

**Small update: Thanks for the quick response guys, I've been battling with this assignment for quite some time and finally finished it.

CodePudding user response:

There are possible problems with your code.

CODESANDBOX DEMO

use onChange instead of onInput as

onChange={ ( e ) => setTodoInp( e.target.value ) }

You have to pass a function to onClick, you are invoking it. So it should be as:

onClick={ () => addTodo( todoInp ) }

You have to return a new array so that react comes to know when to re-render the component. If you pass same array then react won't re-render it.

  setTodos( ( prev ) => ( [
    ...prev,
    {
      id: startingId  ,
      title: title,
      createdAt: new Date().toLocaleTimeString(),
      isComplete: false,
    }
  ] ) );

You should pass a unique id to each element in an array when you use map in JSX.

You can create a new state as

const [startingId, setstartingId] = useState(0);

and increment it as:

setTodos((prev) => [
    ...prev,
    {
        id: startingId   1,
        title: title,
        createdAt: new Date().toLocaleTimeString(),
        isComplete: false,
    },
]);
setstartingId((id) => id   1);

CodePudding user response:

You don't need to pass the addTodo function to onClick with parentheses because you are actually passing addTodo returned result. But in your case, you also need to pass title to the addTodo function so, you need to give onClick a callback function.

<button
  className="btn btn-outline-primary"
  type="button"
  id="button-addon2"
  onClick={() => addTodo(todoInp)}
>
  Add Todo
</button>

CodePudding user response:

everything you did is correct except for the fact that you didn't pass the title parameter in the "Input" component,thus title is undefined and the if condition is false and the state is not getting updated,please pass the title in the addTodo() function call in "Input" component

  • Related