1

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.

2 Answers 2

4

The easiest, most acceptable way of doing so:

const list = [...prevState.list, thing];
Sign up to request clarification or add additional context in comments.

2 Comments

I see. I am stil receiving the following error: Argument of type '(prevState: MainState) => any[]' is not assignable to parameter of type 'SetStateAction<MainState>. Type '(prevState:MainState) => any[]' is not assignable to type '(prevState: MainState) => MainState'. Property 'list' is missing in type 'any[]' but required in type MainState
Then this will solve part of the problem: setClasses((prevState): MainState => ({ list: [...prevState.list, CLASS] }));. But then on the list in the return of the arrow function I am again receiving the Type 'number' is not assignable to type '0'.
1

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>
}

2 Comments

Receive on the return { list }; the message: Type 'never[]' is not assignable tot type 'readonly[]'. Types of property 'length' are incompatible. Type 'number' is not assignable to type '0'.
Updated answer, there was no type of array in your state definition

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.