MeltingDog
MeltingDog

Reputation: 15404

React: how to lift props up to parent component?

I'm new to React and am following a tutorial.

I'm at a stage where I need to lift props up from child to parent components. For the time being I have a simple function on the parent component that just console.logs the retrieved value from the child.

However, it doesn't work. I just get undefined in my console.log. I'm unsure what I've done wrong as it appears the same as the example in the tutorial.

Can anyone help me out?

Here's my parent component:

import React from 'react';
import ExpensesFilter from '../ExpensesFilter/ExpensesFilter';
import ExpenseItem from "./ExpenseItem";
import Card from "../Ui/Card";
import './Expenses.css';

const Expense = (props) => {

  const yearChangeHandler = (chosenYear) => {
    console.log(chosenYear); // Returns Undefined
  }

  return (
    <div>
      <ExpensesFilter onYearChange={yearChangeHandler}/>
      <Card className="expenses">
        <ExpenseItem title={props.items[0].title} amount={props.items[0].amount} date={props.items[0].date} />
    </div>
  );
}

export default Expense;

And my child component:

import React, { useState } from 'react';

import './ExpensesFilter.css';

const ExpensesFilter = (props) => {
  const [selectedYear, setSelectedYear] = useState('');
  const yearChangeHandler = (event) => {
    const chosenYear = setSelectedYear(event.target.value);
    props.onYearChange(chosenYear); 
  };

  return (
    <div className='expenses-filter'>
      <div className='expenses-filter__control'>
        <label>Filter by year</label>
        <select onChange={yearChangeHandler}>
          <option value='2022'>2022</option>
          <option value='2021'>2021</option>
          <option value='2020'>2020</option>
          <option value='2019'>2019</option>
        </select>
      </div>
    </div>
  );
};

export default ExpensesFilter;

My goal is to console.log the selected year in the parent component. Any help is appreciated. Thanks!

Upvotes: 2

Views: 744

Answers (2)

Shoyeb Memon
Shoyeb Memon

Reputation: 1149

The value which you are passing 'setSelectedYear' directly might not getting set due to async behaviour of useState .

try passing the target.value instead.

const [selectedYear, setSelectedYear] = useState('');
const yearChangeHandler = (event) => {
  const chosenYear = event.target.value;
  setSelectedYear(chosenYear);
  props.onYearChange(chosenYear); 
};

Upvotes: 0

Lin Du
Lin Du

Reputation: 102247

setSelectedYear returns void. The signatures of useState and setState are:

function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];

type Dispatch<A> = (value: A) => void;

Try

import React, { useState } from 'react';

import './ExpensesFilter.css';

const ExpensesFilter = (props) => {
  const [selectedYear, setSelectedYear] = useState('');
  const yearChangeHandler = (event) => {
    const chosenYear = event.target.value;
    setSelectedYear(chosenYear);
    props.onYearChange(chosenYear); 
  };

  return (
    <div className='expenses-filter'>
      <div className='expenses-filter__control'>
        <label>Filter by year</label>
        <select onChange={yearChangeHandler}>
          <option value='2022'>2022</option>
          <option value='2021'>2021</option>
          <option value='2020'>2020</option>
          <option value='2019'>2019</option>
        </select>
      </div>
    </div>
  );
};

export default ExpensesFilter;

Upvotes: 4

Related Questions