I want to use an immutable array to handle the state. And add an item to this list.
interface MainState {
list: readonly []; // define immutable array
}
const Component: React.FC = () => {
// by default use the immutable array with type
const [classes, setClasses] = useState({ list: [] } as MainState);
useEffect(() => {
if (data) {
data.forEach((thing) => {
setClasses(prevState => {
//
// Call signature return types '{ list: never[]; }' and 'MainState' are incompatible.
// The types of 'list.length' are incompatible between these types.
// Type 'number' is not assignable to type '0'. TS2345
//
const list = prevState.list.concat(thing);
return { list };
});
});
}
});
// ...
}
I though using concat would work, since it returns a new array.
From the doc you provided:
The concat() method is used to merge two or more arrays
So you need to pass array, not element to this function, I suppose this will work:
const list = prevState.list.concat([thing]);
Also I see your code is iterating through new array and pass elements one by one, why don't you concat the whole array?
if (data) {
setClasses(prevState => {
const list = prevState.list.concat(data);
// or list = [...prevState.list, ...data];
return { list };
});
}
Also I think you missed type of array in you MainState
, at least update it with any
type, here is full example for number
type:
interface MainState {
list: readonly number[];
}
const data = [1, 2, 3]
const Component: React.FC = () => {
const [classes, setClasses] = useState({ list: [] } as MainState);
useEffect(() => {
if (data) {
setClasses(prevState => ({ list: [...prevState.list, ...data]}));
}
});
return <div>{classes}</div>
}