我正在开发一个预算跟踪应用程序,用户可以在其中添加不同的收入和支出。我使用useReducer来管理状态。每个收入和费用都是一个对象,当用户提交收入或费用时,它将显示为包含收入项目的收入列表或包含费用项目的费用列表。列表中的每个项目都有一个删除按钮,用于删除收入项目或费用项目。但是,当我尝试点击删除按钮来删除收入项目时,我得到一个错误,说列表。Map不是函数
不确定为什么会发生这种情况,但我认为这与IncomeOutputList.js中的removeItem函数有关。删除收入项目的正确方法是什么?
App.js
import React, { useState, useReducer } from 'react';
import './App.css';
import BudgetInput from './components/input/BudgetInput';
import BudgetOutput from './components/output/BudgetOutput';
import IncomeOutputList from './components/output/IncomeOutputList';
import ExpenseOutputList from './components/output/ExpenseOutputList';
const useSemiPersistentState = (key, initialState) => {
// console.log(JSON.parse(localStorage.getItem(key)));
const [value, setValue] = React.useState(
localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key)) : initialState
);
React.useEffect(()=>{
localStorage.setItem(key, JSON.stringify(value));
}, [value, key])
return [value, setValue];
};
const initialBudget = {
description: '',
type: '+',
key: 'income',
value: ''
};
const initialState = {
incomes: [{}],
expenses: [{}],
budgetObj: initialBudget
};
const budgetReducer = (state, action) => {
switch(action.type) {
case "CHECK_STATE":
console.log(state); //just to check state on submit
case "ON_DESC_CHANGE":
return {
...state,
budgetObj: {
...state.budgetObj,
description: action.payload
}
}
case "ON_TYPE_CHANGE":
const isExpense = action.payload === '-';
return {
...state,
budgetObj: {
...state.budgetObj,
type: action.payload,
key: isExpense ? 'expense' : 'income'
}
}
case "ON_VALUE_CHANGE":
return {
...state,
budgetObj: {
...state.budgetObj,
value: action.payload,
}
}
case 'SUBMIT_BUDGET':
console.log(state.incomes);
const budget = {...state};
const isIncome = budget.budgetObj.type === '+';
return {
incomes: isIncome ? state.incomes.concat(budget.budgetObj) : state.incomes,
expenses: isIncome ? state.expenses : state.expenses.concat(budget.budgetObj),
budgetObj: initialBudget,
}
case "REMOVE_ITEM":
console.log('test');
return {
...state,
// not sure if the following line is the correct way to remove from local storage
incomes: (index) => JSON.parse(localStorage.getItem("income")).splice(index,1),
// expenses: (index) => JSON.parse(localStorage.getItem("expense")).splice(index,1)
}
default:
return state;
}
}
const useSemiPersistantReducer = (key, initialState) => {
const [value, dispatch] = React.useReducer(
budgetReducer,
localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key)) : initialState
);
React.useEffect(()=>{
localStorage.setItem(key, JSON.stringify(value));
}, [value, dispatch]) //[inocmes, setIncomes]
return [value, dispatch];
}
const App = () => {
const [budgetState, setBudget] = useSemiPersistantReducer(initialState.budgetObj.key,initialState);
const {incomes, expenses, budgetObj, key} = budgetState;
return (
<div className="App">
<link href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css"></link>
<div className="top">
<BudgetOutput />
</div>
<div className="bottom">
<BudgetInput
descValue={budgetObj.description || ''} //event.target.value
onDescChange={event => setBudget({ type: "ON_DESC_CHANGE", payload: event.target.value })}
onSelectChange={event => setBudget({ type: "ON_TYPE_CHANGE", payload: event.target.value })}
type={budgetObj.type || ''}
onBudgetSubmit={ () => setBudget({ type : 'SUBMIT_BUDGET' }) }
budgetValue={budgetObj.value || ''}
onValChange={event => setBudget({ type: "ON_VALUE_CHANGE", payload: event.target.value })}
/>
<div className="container clearfix">
<IncomeOutputList
list={incomes}
removeIncome={ () => setBudget({ type: "REMOVE_ITEM" })} //not sure if this is correct?
/>
<ExpenseOutputList
list={expenses}
// removeExpense={(index)=>removeExp(index)}
/>
</div>
</div>
</div>
)
};
export default App;
IncomeOutput.js
import React from 'react';
import IncomeOutput from './IncomeOutput';
// list will be list of income objects
const IncomeOutputList = ({ list, removeIncome }) => {
return (
<div className="income__list">
<div className="income__list--title">INCOME</div>
{list.map((item, index, arr) => <IncomeOutput
id={item.id}
value={item.value}
type={item.type}
desc={item.description}
// error has something to do with the following line?
handleButton={()=>removeIncome(index)}
/>
)}
</div>
)
}
export default IncomeOutputList;
IncomeOutput.js
import React from 'react';
import ValueOutput from './ValueOutput';
const IncomeOutput = ({ desc, type,id, value, handleButton }) => {
return (
<>
<div className="item clearfix income" id={id}>
<div className="item__description">{desc}</div>
<ValueOutput
type={type}
value={value}
handleClick={handleButton}
/>
</div>
</>
)
}
export default IncomeOutput;
ValueOutput.js
import React from 'react';
import Button from '../buttons/Button';
const ValueOutput = ({type, value, handleClick}) => {
return (
<>
<div className="right clearfix">
<div className="item__value">{type} {value}</div>
<Button buttonType="item__delete--btn" handler={handleClick}/>
</div>
</>
)
}
export default ValueOutput;
Button.js
import React from 'react';
const Button = ({buttonType, handler}) => (
<>
<div className="item__delete">
<button className={buttonType} onClick={handler}>
<i className="ion-ios-close-outline"></i>
</button>
</div>
</>
)
export default Button;
我没有运行你的代码,只是一个猜测
income: (index) =>JSON.parse (localStorage.getItem("income" .splice(指数(1),
incomes是一个函数而不是数组,因此"income .map()"不存在