skip to Main Content

This is the code I want to make work. When I click button everything remains the same.

Console.log does change though. What is wrong? Thanks

import React, {useState} from 'react';
import ExpenseDate from './ExpenseDate';
import Card from '../UI/Card';
import './ExpenseItem.css';

function ExpenseItem(props) {

const [title, setTitle]= useState(props.title);

const clickHandler=()=>{

    setTitle('Updated!');
    console.log(title);
};

    return (
    
    <Card className='expense-item'>
        
          <ExpenseDate date={props.date}></ExpenseDate>      
  
        <div className='expense-item__description'>
            <h2>{props.title}</h2>
            <div className='expense-item__price'>${props.amount}</div>
        </div>
        <button onClick={clickHandler}>Change title</button> 
    </Card>
    );
}

export default ExpenseItem;

5

Answers


  1. You are passing props.title instead of title in your HTML. Even though your state value is updating, you are not using this value. Instead, you are using the initial value passed by your component props.

    Login or Signup to reply.
  2. Change this in your code. As pointed out, you are using wrong variable to print the data.

    <h2>{props.title}</h2> to <h2>{title}</h2>

    Login or Signup to reply.
  3. Although there has been an answer already, I thought i’d make things a bit more clear here, from a wider point of view.

    Say you have ComponentA which provides a title to ComponentB via props:

    const ComponentA = () => {
        return <ComponentB title={"Test"} />
    }
    
    const ComponentB = (props) => {
        const [title, setTitle] = useState(props.title)
        return <h1>{props.title}</h1>
    }
    

    Here what you are essentially doing is telling ComponentB to take its initial state from props.title, but during the lifecycle of the component, you are changing title, however, in the h1 tag you are still rendering props.title and not title which is the title in your state.

    To get around this, you can do 2 things: render title instead of props.title in your h1, or lift the state to ComponentA in order to have a more clear and strict control of what the UI renders:

    const ComponentA = () => {
        const [title, setTitle] = useState("some title")
    
        return (
            <ComponentB 
                title={title}
                setTitle={setTitle}
            />
        )
    }
    
    const ComponentB = ({title, setTitle}) => {
    
        return (
            <div>
                <h1>{title}</h1>
                <input value={title} onChange={e => setTitle(e.target.value)} />
            </div>
        )
    }
    

    This way, you only have one title, which gets rid of the confusion. In most cases, reducing the number of variables is a good practice as long as it serves to simplify the code and it does not interfere with other things in your application.

    Login or Signup to reply.
  4. In react, the main difference between state and props is that state is mutable while props is not. So if you want to update the value you must use local state instead of props.

    Login or Signup to reply.
  5. Seems like you are rendering the props instead of the state. Rather than <h2>{props.title}</h2> please retry with <h2>{title}</h2>

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search