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.
CodePudding user response:
You are going to kick yourself:
You are writing
dispatch({
type: 'fetch',
payload: {
data: d
}
})
when you should just write
dispatch({
type: 'fetch',
payload: d
})
Incidentally, I would rewrite the whole thing as
useEffect( () => {
// TODO: Call fetch action
const doFetch = async() => {
const payload = await getMovies();
console.log('payload', payload)
dispatch({
type: 'fetch',
payload
});
};
doFetch();
}, []);
Which is (imo) more readable.
One thing you should notice here is the huge advantage that Typescript gives you. If you made the same mistake in Javascript, you would not find out about it until some consumer of the store failed at some point in the future.
CodePudding user response:
The error message state's the obvious error. Your passing payload
with type {data:Movie[]}
and in your Moviestate
the 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 };