Adding Event Listeners Made Easy
Adding Event Listeners Made Easy
Adding Event Listeners Made Easy
Watch video 1 and 2 from the following link and add event listeners to the button.
<button onClick={()=>{console.log("hi")}}>Delete</button>
When you write onClick={clickHandler()}, you're actually calling the function immediately
when the component renders, and whatever is returned from clickHandler is then assigned
as the event handler. This is not what you want. You want to assign the clickHandler function
itself as the event handler, so it will be called when the button is clicked, not when the
component renders.
// import './Expense.css';
import './ExpenseItem.css';
import ExpenseDate from './ExpenseDate';
function ExpenseItem(props){
const clickHandler = ()=>{
console.log("hello!")
}
return (
<Card className="expense-item">
<ExpenseDate date={props.date}/>
<div className="expense-item__description">
<h2>{props.title}</h2>
<div className="expense-item__price">{props.amount}</div>
</div>
<button onClick={clickHandler}>Delete</button>
</Card>
)
}
export default ExpenseItem;
https://github.com/pandey0801/Adding-Event-Listeners-/upload/main
03/02/2024
Que. [Super Important Question] - When does useState initialize the state.
Ans. In React, the useState hook initializes the state when the component is first rendered.
When you call useSate(initialValue) , React sets up the initial state with the provided initialVlaue. This
happens during the initial render of the component.
Que. [Super Important Question] - What happens when you update the state using setTitle
Ans. When you update the state using SetTitle():
1. The state value is updated to newValue.
2. React schedules a re-render of the component.
3. During re-render, the UI reflects the new state value.
4. React efficiently updates the DOM to reflect the changes.
// import './Expense.css';
function ExpenseItem(props){
return (
<Card className="expense-item">
<ExpenseDate date={props.date}/>
<div className="expense-item__description">
<h2>{props.title}</h2>
<div className="expense-item__price">{amount}</div>
</div>
<button onClick={clickHandler}>Delete</button>
</Card>
)
}
export default ExpenseItem;
Functional Class
Components Components
because react never repeat step (render). once it executed it over the step
1.useState function in React returns an array with two elements:
https://github.com/pandey0801/Manipulating-the-DOM---React-States
ExpenseForm.js
import './ExpenseForm.css'
<div className='new-expense__controls'>
<label>Amount</label>
<input type='number' min="0.01" step="0.01"/>
</div>
<div className='new-expense__controls'>
<label>Date</label>
<input type='date' min="2019-01-01" max="2022-12-31"/>
</div>
<div className='new-expense__actions'>
<button type='submit'>Add Expense</button>
</div>
</div>
</form>
)
}
ExpenseForm.js
import './NewExpense.css';
import ExpenseForm from './ExpenseForm';
.new-expense__controls {
display: flex;
flex-wrap: wrap;
gap: 1rem;
margin-bottom: 1rem;
text-align: left;
}
.new-expense__control label {
font-weight: bold;
margin-bottom: 0.5rem;
display: block;
}
.new-expense__control input {
font: inherit;
padding: 0.5rem;
border-radius: 6px;
border: 1px solid #ccc;
width: 20rem;
max-width: 100%;
}
.new-expense__actions {
text-align: right;
}
NewExpense.css
.new-expense {
background-color: #a892ee;
padding: 1rem;
margin: 2rem auto;
width: 50rem;
max-width: 95%;
border-radius: 12px;
text-align: center;
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.25);
}
.new-expense button {
font: inherit;
cursor: pointer;
padding: 1rem 2rem;
border: 1px solid #40005d;
background-color: #40005d;
color: white;
border-radius: 12px;
margin-right: 1rem;
}
.new-expense button:hover,
.new-expense button:active {
background-color: #510674;
border-color: #510674;
}
.new-expense button.alternative {
color: #220131;
border-color: transparent;
background-color: transparent;
}
.new-expense button.alternative:hover,
.new-expense button.alternative:active {
background-color: #ddb3f8;
}
06Stepping into the shoes of an Interviewer
https://github.com/pandey0801/Creating-your-own-first-Component
DELIVERABLE
1. Add a state called enteredtitle and update this whenever the user changes the title.
2. Similarly add a state called enteredAmount and update this whenever the user changes the
amount
3. Similarly add a state called enteredDate and update this whenever the Date changes.
const dateChangeHandler=(event)=>{
setEnteredDate(event.target.value)
}
return(
<form>
<div className='new-expense__controls'>
<div className='new-expense__controls'>
<label>Title</label>
<input type='text' onChange={titleChangeHandeler}/>
</div>
<div className='new-expense__controls'>
<label>Amount</label>
<input type='number' min="0.01" step="0.01"
onChange={amountChangeHandler}/>
</div>
<div className='new-expense__controls'>
<label>Date</label>
<input type='date' min="2019-01-01" max="2022-12-31"
onChange={dateChangeHandler}/>
</div>
<div className='new-expense__actions'>
<button type='submit'>Add Expense</button>
</div>
</div>
</form>
)
}
export default ExpenseForm;
Design patterns with state
we using this because we wat latest state for update. that why we passing uerInput to the
function. and copy that
When the user clicks on the submit button create an object and log it on the screen. Its very
easy. TRY IT BY YOURSELF.
const submitHandler=(event)=>{
event.preventDefault();
console.log("clicke");
console.log(enteredTitle);
console.log(enteredAmount);
console.log(enteredDate);
}
<div className='new-expense__actions'>
<button type='submit' onClick={submitHandler}>Add Expense</button>
</div>
// console.log(setEnterTitle(event.target.value));
// console.log(setEnterTitle)
const dateChangeHandler=(event)=>{
setEnteredDate(event.target.value)
}
const submitHandler=(event)=>{
event.preventDefault();
const expenseData = {
Titel: enteredTitle,
amount: enteredAmount,
date: new Date (enteredDate)
}
console.log(expenseData);
}
return(
<form onSubmit={submitHandler}>
<div className='new-expense__controls'>
<div className='new-expense__controls'>
<label>Title</label>
<input type='text' onChange={titleChangeHandeler}/>
</div>
<div className='new-expense__controls'>
<label>Amount</label>
<input type='number' min="0.01" step="0.01"
onChange={amountChangeHandler}/>
</div>
<div className='new-expense__controls'>
<label>Date</label>
<input type='date' min="2019-01-01" max="2022-12-31"
onChange={dateChangeHandler}/>
</div>
<div className='new-expense__actions'>
<button type='submit'>Add Expense</button>
</div>
</div>
</form>
)
}
https://github.com/pandey0801/Submitting-the-forms
Two-way data binding is a technique that allows data to flow in both directions between a user
interface (UI) and the application's state. This means that when a user changes the value of a UI
element, the state is updated automatically, and vice versa.
import React, { useState } from 'react';
function TwoWayBindingExample() {
// Initialize state with an empty string
const [value, setValue] = useState('');
return (
<div>
{/* Input field controlled by state */}
<input
type="text"
value={value}
onChange={handleChange}
/>
{/* Display the value from state */}
<p>Value: {value}</p>
</div>
);
}
the value attribute of the input element is set to value, which is controlled by React state.
When the user types in the input field, the onChange event handler updates the state with the
new value. As a result, changes made by the user in the input field are immediately reflected in
the displayed value
Parent code
function ParentComponent() {
const handleDataFromChild = (data) => {
console.log("Data from child:", data);
};
return <ChildComponent onData={handleDataFromChild} />;
}
Child code
function ChildComponent({ onData }) {
const sendDataToParent = () => {
const data = "Hello from child";
onData(data);
};
callback functions are often used for child-to-parent component communication, allowing child
components to pass data or trigger actions in their parent components.
"Lifting state up" is a common pattern in React where you move the state from a lower-level
component to a higher-level component in the component tree. This pattern allows you to
share state between components and manage it in a single location, typically in a common
ancestor of the components that need access to the state.
ExpenseFrom.js
// console.log(setEnterTitle(event.target.value));
// console.log(setEnterTitle)
const dateChangeHandler=(event)=>{
setEnteredDate(event.target.value)
}
const submitHandler=(event)=>{
event.preventDefault();
const expenseData = {
Titel: enteredTitle,
amount: enteredAmount,
date: new Date (enteredDate)
}
props.onSaveExpenseData(expenseData);
setEnterTitle('')
setEnteredAmount('')
setEnteredDate('')
}
return(
<form onSubmit={submitHandler}>
<div className='new-expense__controls'>
<div className='new-expense__controls'>
<label>Title</label>
<input type='text'
value={enteredTitle}
onChange={titleChangeHandeler}/>
</div>
<div className='new-expense__controls'>
<label>Amount</label>
<input type='number'
min="0.01"
step="0.01"
value={enteredAmount}
onChange={amountChangeHandler}/>
</div>
<div className='new-expense__controls'>
<label>Date</label>
<input type='date'
min="2019-01-01"
max="2022-12-31"
value={enteredDate}
onChange={dateChangeHandler}/>
</div>
<div className='new-expense__actions'>
<button type='submit'>Add Expense</button>
</div>
</div>
</form>
)
}
NewExpense.js
import './NewExpense.css';
return(
<div className='new-expense'>
<ExpenseForm onSaveExpenseData ={saveExpenseDataHandler}/>
</div>
)
}
App.js
// import logo from './logo.svg';
// import './App.css';
// import './components/Expense.css'
import './components/Expenses/Expense.css'
import ExpenseItem from "./components/Expenses/ExpenseItem";
import Card from './components/UI/Card';
import NewExpense from './components/NewExpense/NewExpense';
const expenses = [
{
id: 'e1',
title: 'Toilet Paper',
amount: 94.12,
date: new Date(2020, 7, 14),
},
{ id: 'e2',
title: 'New TV',
amount: 799.49,
date: new Date(2021, 2, 12)
},
{
id: 'e3',
title: 'Car Insurance',
amount: 294.67,
date: new Date(2021, 2, 28),
},
{
id: 'e4',
title: 'New Desk (Wooden)',
amount: 450,
date: new Date(2021, 5, 12),
},
];
return (
<div>
<NewExpense onAddExpense={AddExpenseHandler} />
<Card className="expenses">
</Card>
</div>
);
}
Task details
One common problem with the website is that the input forms still hold onto the old value.
Check video 13 from following link to understand how you can solve this problem.
[Very Important Video] - Watch video 14 and 15 from above link and solve the problem of dynamically
updating the expense array whenever the user fills the input form. Code along with the udemy trainer and
answer the following.
1. Can you tell the exact flow of data from ExpenseForm component to Expense Component as per the
trainer
2. Why did we have to lift the state up from NewExpense component to App component. Why cant we
directly talk between NewExpense and Expense Component?
Deliverable
Can you now utilize the addExpenseHandler function in APP.js in such a way that it starts showing
dynamically in the UI. Try it by yourself. It is super simple now.
1.we getting the data from ExpenseForm. we passing the data to NewExpense from
ExpenseForm. and passing the data from ExpenseForm to App.js
2.bacause we want all the data in one place. we move the state from a lower-level
component to a higher-level component in the component tree. This pattern allows
you to share state between components and manage it in a single location.
https://github.com/pandey0801/Making-the-expense-form-input-visible-on-screen
https://github.com/pandey0801/Making-the-expense-form-input-visible-on-screen
06/02/2024
Controlled Components:
Uncontrolled Components:
Form elements manage their own state internally using the DOM.
Value changes do not trigger state updates or re-renders.
Useful for integrating with non-React code or third-party libraries.
State management delegated to the DOM.
Filter.js
import './ExpenseFilter.css';
.expenses-filter {
color: white;
padding: 0 1rem;
align-items: center;
}
.expenses-filter__control {
/* display: flex; */
width: 100%;
align-items: center;
justify-content: space-between;
margin: 1rem 0;
}
.expenses-filter label {
font-weight: bold;
margin-bottom: 0.5rem;
}
.expenses-filter select {
font: inherit;
padding: 0.5rem 3rem;
font-weight: bold;
border-radius: 6px;
}
App.js
// import logo from './logo.svg';
// import './App.css';
// import './components/Expense.css'
import './components/Expenses/Expense.css'
import ExpenseItem from "./components/Expenses/ExpenseItem";
import Card from './components/UI/Card';
import NewExpense from './components/NewExpense/NewExpense';
const expenses = [
{
id: 'e1',
title: 'Toilet Paper',
amount: 94.12,
date: new Date(2020, 7, 14),
},
{ id: 'e2',
title: 'New TV',
amount: 799.49,
date: new Date(2021, 2, 12)
},
{
id: 'e3',
title: 'Car Insurance',
amount: 294.67,
date: new Date(2021, 2, 28),
},
{
id: 'e4',
title: 'New Desk (Wooden)',
amount: 450,
date: new Date(2021, 5, 12),
},
];
return (
<div>
<NewExpense onAddExpense={AddExpenseHandler} />
<ExpensesFilter selected={filteredYear}
onChangeFilter={filterChangeHandler}/>
{/* <ExpensesFilter/> */}
<Card className="expenses">
</Card>
</div>
);
}
https://github.com/pandey0801/PlaceHolder---Adding-a-filter-which-doesnt-work-on-the-
expense-tracker
Rendering Expenses with performance optimisations
001 Module Introduction
002 Rendering Lists of Data
{expenses.map(expense => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
))}
Watch video 1 and 2 from the following link and code along with the Udemy trainer and answer the
following.
1. Why did the Udemy trainer even convert the code. Why doesn't he use ExpenseItem Component -> 4
times for showing 4 expenses. What do you think is the reason?
Watch video 3 from above link , code along with the udemy trainer and answer the following
1. Why does the trainer uses state and not update the old expense variable. If you update the old expense
variable like this expenses.push(expense). Why does this not work?
Watch video 4 from above link, code along with the udemy trainer and answer the following.[Very
important for performance enhacement]
ans
1. using dynamic rendering. we don't know how many list item does Expenses have
2. for updating the state we will use usestate and separator operator to copy the old array item list
3. When you don't use keys in a list of elements in React, it can lead to issues with performance, state
management, and component reusability
4. using keys in React provides several benefits, including improved rendering performance, stable
component identity, prevention of reordering issues, optimized DOM operations, and enhanced
component reusability
5. using the index of an element as its key may seem convenient, it is generally not recommended in React
due to its lack of stability, limited usefulness, potential performance implications, accessibility concerns,
and potential for bugs and errors
https://github.com/pandey0801/Rendering-Expenses-with-performance-optimisations
7/2/2024
import './components/Expenses/Expense.css'
import ExpenseItem from "./components/Expenses/ExpenseItem";
import Card from './components/UI/Card';
import NewExpense from './components/NewExpense/NewExpense';
const DUMMY_EXPENSES = [
{
title: 'Toilet Paper',
amount: 94.12,
date: new Date(2020, 7, 14),
id: 'e1',
},
{
title: 'New TV',
amount: 799.49,
date: new Date(2021, 2, 12),
id: 'e2',
},
{
title: 'Car Insurance',
amount: 294.67,
date: new Date(2021, 2, 28),
id: 'e3',
},
{
title: 'New Desk (Wooden)',
amount: 450,
date: new Date(2021, 5, 12),
id: 'e4',
},
];
// )
};
// // {arr==filteredYear?console.log("true"):console.log("false")}
// const fl = arr.filter(x=>{
// return x==filteredYear
// })
// // console.log(fl);
// console.log(filteredYear);
// console.log(filteredExpenses);
return (
<div>
<NewExpense onAddExpense={AddExpenseHandler} />
<Card className="expenses">
<ExpensesFilter selected={filteredYear}
onChangeFilter={filterChangeHandler}/>
{filteredExpenses.map(expense => (
<ExpenseItem
title={expense.title}
amount={expense.amount}
date={expense.date}
key={expense.id}
/>
))}
</Card>
</div>
);
}
https://github.com/pandey0801/Implementing-the-filter-feature
Conditional Rendering
import './components/Expenses/Expense.css'
import ExpenseItem from "./components/Expenses/ExpenseItem";
import Card from './components/UI/Card';
import NewExpense from './components/NewExpense/NewExpense';
const DUMMY_EXPENSES = [
{
title: 'Toilet Paper',
amount: 94.12,
date: new Date(2020, 7, 14),
id: 'e1',
},
{
title: 'New TV',
amount: 799.49,
date: new Date(2021, 2, 12),
id: 'e2',
},
{
title: 'Car Insurance',
amount: 294.67,
date: new Date(2021, 2, 28),
id: 'e3',
},
{
title: 'New Desk (Wooden)',
amount: 450,
date: new Date(2021, 5, 12),
id: 'e4',
},
];
// )
};
// const fl = arr.filter(x=>{
// return x==filteredYear
// })
// // console.log(fl);
// console.log(filteredYear);
// console.log(filteredExpenses);
return (
<div>
<NewExpense onAddExpense={AddExpenseHandler} />
<Card className="expenses">
<ExpensesFilter selected={filteredYear}
onChangeFilter={filterChangeHandler}/>
return(
<div className='expenses-list'>
{props.item.map((expense) => (
<ExpenseItem
title={expense.title}
amount={expense.amount}
date={expense.date}
key={expense.id}
/>
))}
</div>
)
}
.expenses-list {
list-style: none;
padding: 0;
}
.expenses-list__fallback {
color: white;
text-align: center;
}
App.js
import './components/Expenses/Expense.css'
// import ExpenseItem from "./components/Expenses/ExpenseItem";
import Card from './components/UI/Card';
import NewExpense from './components/NewExpense/NewExpense';
import ExpensesFilter from './components/Expenses/ExpenseFilter';
import ExpensesList from './components/Expenses/ExpensesList';
const DUMMY_EXPENSES = [
{
title: 'Toilet Paper',
amount: 94.12,
date: new Date(2020, 7, 14),
id: 'e1',
},
{
title: 'New TV',
amount: 799.49,
date: new Date(2021, 2, 12),
id: 'e2',
},
{
title: 'Car Insurance',
amount: 294.67,
date: new Date(2021, 2, 28),
id: 'e3',
},
{
title: 'New Desk (Wooden)',
amount: 450,
date: new Date(2021, 5, 12),
id: 'e4',
},
];
// )
};
// // {arr==filteredYear?console.log("true"):console.log("false")}
// const fl = arr.filter(x=>{
// return x==filteredYear
// })
// // console.log(fl);
// console.log(filteredYear);
// console.log(filteredExpenses);
return (
<div>
<NewExpense onAddExpense={AddExpenseHandler} />
<Card className="expenses">
<ExpensesFilter selected={filteredYear}
onChangeFilter={filterChangeHandler}/>
<ExpensesList item={filteredExpenses}/>
{/* {filteredExpenses.length===0 && <p>No Elemnet</p>}
{filteredExpenses.length===1 && <p>Only single Expense here. Please add
more...</p>}
{filteredExpenses.length>0 && filteredExpenses.map(expense => (
<ExpenseItem
title={expense.title}
amount={expense.amount}
date={expense.date}
key={expense.id}
/>
))} */}
import './NewExpense.css';
import ExpenseForm from './ExpenseForm';
import React, {useState} from 'react';
const NewExpense = (props) =>
{
const [showCustomComponent, setShowCustomComponent] = useState(false);
setShowCustomComponent(false);
}
return(
<div className='new-expense'>
// console.log(setEnterTitle(event.target.value));
// console.log(setEnterTitle)
const dateChangeHandler=(event)=>{
setEnteredDate(event.target.value)
// console.log(event.target.value);
// console.log(enteredDate);
const submitHandler=(event)=>{
event.preventDefault();
const expenseData = {
title: enteredTitle,
amount: enteredAmount,
date: new Date (enteredDate)
// data: enteredDate
}
// console.log(expenseData);
// Props.onSaveExpenseData(expenseData);
// console.Consolelog(Props.onSave(expenseData))
// Props.onSave(expenseData);
setEnterTitle('')
setEnteredAmount('')
setEnteredDate('')
}
return(
<form onSubmit={submitHandler}>
<div className='new-expense__controls'>
<div className='new-expense__controls'>
<label>title</label>
<input type='text'
value={enteredTitle}
onChange={titleChangeHandeler}/>
</div>
<div className='new-expense__controls'>
<label>Amount</label>
<input type='number'
min="0.01"
step="0.01"
value={enteredAmount}
onChange={amountChangeHandler}/>
</div>
<div className='new-expense__controls'>
<label>Date</label>
<input type='date'
// min="2019-01-01"
// max="2022-12-31"
value={enteredDate}
onChange={dateChangeHandler}/>
</div>
<div className='new-expense__actions'>
<button type='button'
onClick={props.onCancel}>Cancel</button>
<button type='submit'>Add Expense</button>
</div>
</div>
</form>
)
}
https://github.com/pandey0801/DIY---Challenges-on-Conditional-Rendering
Chart App
https://github.com/pandey0801/Chart-App