#javascript #reactjs #web #components #typeerror
#javascript #reactjs #веб #Компоненты #ошибка типа
Вопрос:
Я создаю приложение для практики реагирования, и я получаю сообщение об ошибке при попытке сохранить массив объектов в локальном хранилище. Я новичок в React, поэтому я не уверен, что происходит. Я получаю ошибку в компоненте IncomeOutputList, потому что я пытаюсь перечислить кучу объектов, используя массив.
Вот мой код:
Компонент приложения:
import React, { useState, useReducer } from 'react';
import BudgetInput from './components/input/BudgetInput';
import IncomeOutputList from './components/output/IncomeOutputList';
import IncomeOutput from './components/output/IncomeOutput';
const useSemiPersistentState = (key, initialState) => {
const [value, setValue] = React.useState(
localStorage.getItem(key) || initialState
);
React.useEffect(()=>{
localStorage.setItem(key, JSON.stringify(value));
}, [value, key])
return [value, setValue];
};
const App = () => {
const [incomes, setIncomes] = useSemiPersistentState('income',[{}]);
const [description, setDescription] = useState('');
const [type, setType] = useState(' ');
const [value, setValue] = useState('');
const incomeObj = {
desc: description,
budgetType: type,
incomeValue: value
}
const handleIncomeObjArray = () => {
setIncomes(incomes.concat(incomeObj));
console.log(incomes "testing");
}
const handleChange = (event) => { //this handler is called in the child component BudgetInput
setDescription(event.target.value);
}
const handleSelectChange = (event) => { //this handler is called in the child component BudgetInput
setType(event.target.value);
}
const handleValueChange = (event) => {
setValue(event.target.value);
console.log(incomeObj)
}
return (
<div className="App">
<div className="top">
</div>
<div className="bottom">
<BudgetInput
descValue={description}
onDescChange={handleChange}
onSelectChange={handleSelectChange}
type={type}
onBudgetSubmit={handleIncomeObjArray}
budgetValue={value}
onValChange={handleValueChange}
/>
{/* <IncomeOutput
obj={incomeObj}
/> */}
{/* <IncomeOutput
desc={description}
type={type}
/> */}
<IncomeOutputList
list={incomes}
/>
</div>
</div>
)
};
Компонент IncomeOutputList:
import React from 'react';
import IncomeOutput from './IncomeOutput';
// list will be list of income objects
const IncomeOutputList = ({ list }) => {
return (
<div>
{list.map(item => <IncomeOutput
id={item.id}
value={item.incomeValue}
type={item.budgetType}
desc={item.desc}
/>)}
</div>
)
}
export default IncomeOutputList;
Компонент IncomeOutput:
import React from 'react';
import ValueOutput from './ValueOutput';
const IncomeOutput = ({ desc, type,id, value }) => {
//id = inc-{id}
return (
<>
<div className="item clearfix" id={id}>
<div className="item__description">{desc}</div>
<ValueOutput
type={type}
value={value}
/>
</div>
</>
)
}
export default IncomeOutput;
РЕДАКТИРОВАТЬ: вот codesandbox для этого кода: https://codesandbox.io/s/busy-shirley-bwhv2?file=/src/App.js:2394-2509
Комментарии:
1. Обычно это означает, что список не является массивом, поэтому он не может иметь функцию map . Я подозреваю, что список не определен из prop. Возможно, создайте codepen, чтобы мы могли точно определить ошибку.
Ответ №1:
Это потому, что ваш пользовательский редуктор возвращает строку, а не массив
попробуйте это
const useSemiPersistentState = (key, initialState) => {
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];
};
Комментарии:
1. Это может быть потому
localStorage.getItem(key)
, что может бытьnull
в первый раз. Измените его iolocalStorage.getItem(key) amp;amp; JSON.parse(localStorage.getItem(key)) || initialState
2. Как насчет React.useState(localStorage.GetItem(ключ) ? JSON.parse(localStorage.GetItem(ключ)) : начальное состояние)
3. @Nithish да, похоже, пока это работает, спасибо!
4. @alti21 Очистите ваш localStorage (уверен, что у вас там недопустимый json) и поместите try catch вокруг JSON.parse(), чтобы в случае сбоя вы могли удалить его с помощью localStorage.remoteItem(key) и использовать initialState по умолчанию