问题描述
我正在开发一个预算跟踪应用,用户可以在其中添加不同的收入和支出。我正在使用 useReducer 来管理状态。每个收入和费用都是一个对象,当用户提交收入或费用时,它会显示为带有收入项目的收入列表或带有费用项目的费用列表。列表中的每个项目都有一个删除按钮,用于删除收入项目或费用项目。但是,例如,当我尝试单击删除按钮来删除收入项时,我收到一条错误消息,指出 list.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,type: action.payload,key: isExpense ? 'expense' : 'income'
}
}
case "ON_VALUE_CHANGE":
return {
...state,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,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;
收入输出.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;
收入输出.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,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;
解决方法
我没有运行你的代码,只是猜测
收入:(index) => JSON.parse(localStorage.getItem("income")).splice(index,1),
incomes 是一个函数而不是数组,所以“incomes.map()”不存在。