Search code examples
reactjstypescriptreduxuse-reducer

How to use/create type of array in Typescript


I have a react project, where I am creating a store. Here is the code:

import React, { useReducer, useEffect } from 'react';
import { v4 as uuid } from 'uuid';

import { Movie, MoviesAction } from 'types';
import { getMovies } from 'api/movies';

interface MoviesState {
  movies: Movie[]
  initialized: boolean
}

export function useMoviesCollection(): [MoviesState, React.Dispatch<MoviesAction>] {
  // TODO: Implement all action processing

  const movieReducer = (state: MoviesState, action: MoviesAction): MoviesState => {
    switch (action.type) {
      case 'fetch':
        
          console.log('ss', state)
          // return {...state}
          return { ...state, movies: action.payload };
         
        // return { ...state };

      case 'add':
        return { ...state };

      case 'delete':
        return { ...state };

      case 'rate':
        return { ...state };

      default:
        return state
    }
  };

  const [state, dispatch] = useReducer(movieReducer, {
    movies: [],
    initialized: false,
  });

  useEffect( () => {
    // TODO: Call fetch action
    
     getMovies().then((d)=>{
      console.log('g', d)
         dispatch({
          type: 'fetch',
          payload: {
              data: d
          }
      })
     })
  }, []);

  return [state, dispatch];
}

In my useEffect hook, I'm trying to call an API and then use the Data/result to pass it inside the dispatch as the action's payload. Even though the API call returns the type Movie[] of movie array but when I set it to inside the state, I get this error message:

Type '{ data: Movie[]; }' is missing the following properties from type 'Movie[]': length, pop, push, concat, and 28 more. 

The getMovies API call's implementation is like this:

import { Movie } from "types"

export const getMovies = async (): Promise<Movie[]> => {
    return require('../data/movies.json')
}

The types/interfaces for MovieAction and Movie are declared as:

export interface Movie {
    id: string,
    title: string,
    subtitle: string,
    description: string,
    imageUrl: string,
    ratings: number[]
}

export interface MovieFetchAction {
    type: 'fetch',
    payload: {
        data: Movie[]
    }
}

Can someone tell me what I have got wrong here? I feel I am passing the right type.


Solution

  • The error message state's the obvious error. Your passing payload with type {data:Movie[]} and in your Moviestatethe type of movies is 'Movie[]'.

    You need to chain call the data property inside your return to return the correct type.

    Use:

    return { ...state, movies: action.payload.data };