'TypeError: props.onSaveExpenseData is not a function

I am leaning how to send data from child to parent component in React

Why I received this error: TypeError: props.onSaveExpenseData is not a function

Please help me because I am at learning phase and due to this error I am stuck on this and I can't continue my further learning of next lectures.

Error shows in child component.

here github link of same file https://github.com/academind/react-complete-guide-code/blob/04-react-state-events/code/07-lifting-the-state-up/src/components/NewExpense/ExpenseForm.js

Here is Parent Component code with file name -NewExpense.js -

    import ExpenseForm from './ExpenseForm'
    import './NewExpense.css'
    
    function NewExpense () {
        const saveExpenseDataHandler = (enteredExpenseData)=> {
            const expenseData = {
                ...enteredExpenseData,
                id: Math.random().toString()
            };
    
            console.log(expenseData);
        } 
        return (
            <div className='expense-item'>
                <ExpenseForm onSaveExpenseData={saveExpenseDataHandler}/>
            </div>
        )
    }
    
    export default NewExpense;

and this is child component with file name ExpenseForm.js

import React, { useState } from "react";
import './ExpenseForm.css'

function ExpenseForm(props) {

  const [enteredTitle,setEnteredTitle] = useState('');
  const [enteredAmount,setEnteredAmount] = useState('');
  const [enteredDate,setEnteredDate] = useState('');

  const titleChangeHandler = (event) =>{
    setEnteredTitle(event.target.value);
    
  } 
  const amountChangeHandler = (event) =>{
    setEnteredAmount(event.target.value);
    
  }
  const dateChangeHandler = (event) =>{
    setEnteredDate(event.target.value);
    
  }
  
  const submitHandler = (event) => {
    event.preventDefault();
    
    const expenseData = {
      title: enteredTitle,
      amount: enteredAmount,
      date: new Date(enteredDate)
    };

    props.onSaveExpenseData(expenseData);  //here error arrives
    console.log(expenseData);

    setEnteredTitle('');
    setEnteredAmount('');
    setEnteredDate('');
  };

  return (
    <form onSubmit={submitHandler}>
      <div className='new-expense__controls'>
        <div className='new-expense__control'>
          <label>Title</label>
          <input type="text"
           value={enteredTitle}
           onChange={titleChangeHandler} />
        </div>
        <div className='new-expense__control'>
          <label>Amount</label>
          <input type="number" 
           value={enteredAmount}
           onChange={amountChangeHandler} min="0.01" step="0.01" />
        </div>
        <div className='new-expense__control'>
          <label>Date</label>
          <input type="date" 
           value={enteredDate}
           onChange={dateChangeHandler} min="2020-01-01" max="2021-12-31" />
        </div>
        <div className='new-expense__actions'>
        <button type='submit'>Add Expense</button>
      </div>
      </div>
    </form>
  );
}

export default ExpenseForm;

~~~


  [1]: https://github.com/academind/react-complete-guide-code/blob/04-react-state-events/code/07-lifting-the-state-up/src/components/NewExpense/ExpenseForm.js


Solution 1:[1]

I also faced same issue, solution which worked for me is simple. Make sure you have kept space on both sides of '='. After making changes it worked for me. Replace your code line with below working code:-

<ExpenseForm onSaveExpenseData = {saveExpenseDataHandler}/>

Solution 2:[2]

make sure you change the app.js file and add the components

<div>
  <NewExpense onAddExpense={addExpenseHandler} />
  <Expenses items={expenses} />
</div>

Solution 3:[3]

this is basically andrei course

so in the previous component ensure to copy the correct function, since I am following the exact steps per the course in the NewExpense.js file

<div className='new-expense'>
<ExpenseForm onSaveExpenseData={saveExpenseDataHandler}></ExpenseForm>
</div>

Solution 4:[4]

Make sure to Import NewExpense in app.js.

add <NewExpense />component in place of <ExpenseForm /> in App.js . it should look something like this

import NewExpense from "./Components/NewExpense";
function App(){
  return(
   <div>
     <NewExpense />
     */other data*/
   </div>
)

Solution 5:[5]

import NewExpense from './components/NewExpense/NewExpense';

just import the NewExpense.js file into your App.js file

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 cigien
Solution 2 Joseph Hermis
Solution 3 codepikee
Solution 4 Sidharth Mahala
Solution 5 Shimul Chakraborty