I keep getting an “undefined” error in my ReactJS budget allocation app, and it’s been driving me a little crazy! I’m trying to add a dropdown menu for selecting currencies, so when a user chooses an option, the currency should update accordingly. But every time I load the webpage, I keep hitting this “undefined” error. I’m not entirely sure what’s going wrong. I think it might have something to do with the way I’m dispatching the currency change, but I’m stuck and not sure how to fix it. Can anyone take a look at my code and point me in the right direction? I’d really appreciate any advice on what could be causing this!
Error Code:
code// App.js
import ReactJS from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { AppProvider } from './context/AppContext';
import Budget from './components/Budget';
import ExpenseTotal from './components/ExpenseTotal';
import ExpenseList from './components/ExpenseList';
import AllocationForm from './components/AllocationForm';
import RemainingBudget from './components/Remaining';
import Currency from './components/Currency';
const App = () => {
return (
<AppProvider>
<div className='container'>
<h1 className='mt-3'>Company's Budget Allocation</h1>
<div className='row mt-3'>
<div className='col-sm'>
<Budget />
</div>
<div className='col-sm'>
<RemainingBudget />
</div>
<div className='col-sm'>
<ExpenseTotal />
</div>
<div className='col-sm'>
<Currency />
</div>
</div>
<h3 className='mt-3'>Allocation</h3>
<div className='row'>
<div className='col-sm'>
<ExpenseList />
</div>
</div>
<h3 className='mt-3'>Change allocation</h3>
<div className='row mt-3'>
<div className='col-sm'>
<AllocationForm />
</div>
</div>
</div>
</AppProvider>
);
};
export default App;
// Currency.js
import ReactJS, { useState, useContext, useEffect } from 'ReactJS';
import { AppContext } from '../context/AppContext';
const Currency = () => {
const [currency, setCurrency] = useState('');
const { dispatch } = useContext(AppContext);
const handleChange = (event) => {
setCurrency(event.target.value);
changeCurrency(event.target.value);
};
const changeCurrency = (selectedCurrency) => {
dispatch({
type: 'CHG_CURRENCY',
payload: selectedCurrency,
});
};
useEffect(() => {
console.log(currency);
}, [currency]);
return (
<div className="alert alert-secondary">
<select id="inputGroupSelect02" onChange={handleChange}>
<option defaultValue>Currency</option>
<option value="$" name="dollar">$ Dollar</option>
<option value="£" name="pound">£ Pound</option>
<option value="€" name="euro">€ Euro</option>
<option value="₹" name="rupee">₹ Rupee</option>
</select>
</div>
);
};
export default Currency;
This code demonstrates a basic budget allocation application built with ReactJS. The main objective is to provide a layout where users can manage budget allocations, including components for viewing the budget, tracking expenses, and selecting a currency type.
Solution Outline:
- App Structure: The main
App
component wraps the entire application in aAppProvider
context, which shares state among child components. - Components:
Budget
: Displays and manages the total budget.RemainingBudget
: Shows the remaining budget after expenses.ExpenseTotal
: Calculates the total expenses.ExpenseList
: Lists all expenses.AllocationForm
: Allows adjustments in budget allocation.Currency
: Handles currency selection and updates the budget currency.
- Context Setup:
AppContext
manages global state, making it accessible to all components through theuseContext
hook.
Problem in the Code:
The main issue with the code is that changeCurrency()
is called immediately after setCurrency
in the handleChange
function, leading to outdated values in the dispatch
function. This is because setCurrency
is asynchronous, and changeCurrency()
doesn’t get the updated value of currency
.
Correct Code:
code// App.js
import ReactJS from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { AppProvider } from './context/AppContext';
import Budget from './components/Budget';
import ExpenseTotal from './components/ExpenseTotal';
import ExpenseList from './components/ExpenseList';
import AllocationForm from './components/AllocationForm';
import RemainingBudget from './components/Remaining';
import Currency from './components/Currency';
const App = () => {
return (
<AppProvider>
<div className='container'>
<h1 className='mt-3'>Company's Budget Allocation</h1>
<div className='row mt-3'>
<div className='col-sm'>
<Budget />
</div>
<div className='col-sm'>
<RemainingBudget />
</div>
<div className='col-sm'>
<ExpenseTotal />
</div>
<div className='col-sm'>
<Currency />
</div>
</div>
<h3 className='mt-3'>Allocation</h3>
<div className='row'>
<div className='col-sm'>
<ExpenseList />
</div>
</div>
<h3 className='mt-3'>Change allocation</h3>
<div className='row mt-3'>
<div className='col-sm'>
<AllocationForm />
</div>
</div>
</div>
</AppProvider>
);
};
export default App;
// Currency.js
import React, { useState, useContext, useEffect } from 'ReactJS';
import { AppContext } from '../context/AppContext';
const Currency = () => {
const [currency, setCurrency] = useState('');
const { dispatch } = useContext(AppContext);
const handleChange = (event) => {
const selectedCurrency = event.target.value;
setCurrency(selectedCurrency);
changeCurrency(selectedCurrency);
};
const changeCurrency = (selectedCurrency) => {
dispatch({
type: 'CHG_CURRENCY',
payload: selectedCurrency,
});
};
useEffect(() => {
console.log(currency);
}, [currency]);
return (
<div className="alert alert-secondary">
<select id="inputGroupSelect02" onChange={handleChange}>
<option defaultValue>Currency</option>
<option value="$" name="dollar">$ Dollar</option>
<option value="£" name="pound">£ Pound</option>
<option value="€" name="euro">€ Euro</option>
<option value="₹" name="rupee">₹ Rupee</option>
</select>
</div>
);
};
export default Currency;
Explanation of Changes:
handleChange
Adjustment:handleChange
now captures the selected currency value (event.target.value
) inselectedCurrency
and passes this directly tochangeCurrency
. This ensures thatdispatch
is called with the updated currency value immediately.
useEffect
:useEffect
logs the current currency whenever it changes, which is helpful for debugging.
This revised code structure improves performance and avoids potential bugs related to asynchronous state updates in ReactJS. The context setup and component structure enable smooth management and visibility of the budget allocation.