Home > Enterprise >  Typescript react An argument for 'defaultValue' was not provided
Typescript react An argument for 'defaultValue' was not provided

Time:11-24

I have the following code and I get this error (An argument for 'defaultValue' was not provided.).

I need to put in some default values but I can't see which default values.

i also get some other errors:

  1. Property 'imdbID' does not exist on type 'never'. and

  2. Argument of type 'any[]' is not assignable to parameter of type 'SetStateAction<never[]>'. Type 'any[]' is not assignable to type 'never[]'. Type 'any' is not assignable to type 'never'.ts(2345)

  3. Argument of type 'any' is not assignable to parameter of type 'never'.ts(2345) (parameter) movie: any

import React, { createContext, useState, useEffect } from 'react';
import axios from 'axios';
export const MovieContext = createContext();


const MovieApp = ({ children }:any) => {
  const [favorites, setFavorites] = useState([]);
  const [movies, setMovies] = useState();
  const [search, setSearch] = useState('');
  const [selectedMovie, setSelectedMovie] = useState('');

  const fetchMovies = async (searchValue) => {
    const response = await axios(
      `https://www.omdbapi.com/?apikey=${API_KEY}&s=${searchValue}`
    );
    const data = response.data;
    setMovies(data.Search);
  };

  const removeFavoriteMovie = (movie:any) => {
    movie.isFavorite = false;
    const newFavoriteList = favorites.filter(
      (fav) => fav.imdbID !== movie.imdbID
    );
    setFavorites(newFavoriteList);
  };

  const addFavoriteMovie = (movie:any) => {
    movie.isFavorite = true;
    const newFavoriteList = [...favorites, movie];
    setFavorites(newFavoriteList);
  };

  const favoriteHandler = (movie:any, e:any) => {
    e.preventDefault();
    if (favorites.includes(movie)) {
      removeFavoriteMovie(movie);
    } else {
      addFavoriteMovie(movie);
    }
  };

  const showDetail = async (id:any) => {
    const response = await axios(
      `https://www.omdbapi.com/?apikey=${API_KEY}&i=${id}`
    );
    const data = response.data;
    setSelectedMovie(data);
  };

  useEffect(() => {
    console.log(API_KEY)
    fetchMovies(search);
  }, [search]);

  return (
    <MovieContext.Provider
      value={{
        setSearch,
        movies,
        favorites,
        favoriteHandler,
        showDetail,
        selectedMovie,
      }}
    >
      {children}
    </MovieContext.Provider>
  );
};

export default MovieApp;

CodePudding user response:

You need to define what types of data your state should be, for example:

const [movies, setMovies] = useState<TheTypeThatIsReturn>()

// an example of using an array of objects:
const [movies, setMovies] = useState<Array<{id: string, name: string}>>([])

Also you should set a default value for the movies state, as its currently set to nothing and thats why you're getting the 'any[] is not assignable to never[] error.

You'll find it way easier to debug these issues if you stop using 'any', as this will allow all types to pass through and then throw errors which is whole point of Typescript. You can define this at the top of the file using an Interface, or even in a seperate folder/file to store your interfaces and models:

interface IMovieModel {
  id: string;
  name: string;
}
const [movies, setMovies] = useState<Array<IMovieModel>>([])

If you follow these steps you will fix the errors, you will also need to model the API response or at least the parts of it you want to use to stop TS complaining about ID not being found.

CodePudding user response:

If you know the shape of the data that you expect to receive from the api, you can create types to use in your component.

interface Movie {
  Title: string;
  Year: string;
  Rated: string;
  Released: string;
  Runtime: string;
  Genre: string;
  Director: string;
  Writer: string;
  Actors: string;
  Plot: string;
  Language: string;
  Country: string;
  Awards: string;
  Poster: string;
  Ratings?: RatingsEntity[] | null;
  Metascore: string;
  imdbRating: string;
  imdbVotes: string;
  imdbID: string;
  Type: string;
  DVD: string;
  BoxOffice: string;
  Production: string;
  Website: string;
  Response: string;
}
interface RatingsEntity {
  Source: string;
  Value: string;
}

interface Favorite extends Movie {
  isFavorite?: boolean;
}

Then you can specify what the type will be within your state.

  const [favorites, setFavorites] = useState<Favorite[]>([]);
  const [movies, setMovies] = useState<Movie[]>([]);
  const [selectedMovie, setSelectedMovie] = useState<Movie | null>(null);
  const [search, setSearch] = useState<string>("");

CodePudding user response:

React.createContext needs to be passed a default value, that will be used by Consumers not contained by a Provider.

And as everyone else said, if you're not assigning any useful types, why use Typescript in the first place?

type Movie = {
  // ...
}
type MovieContextType = {
  setSearch(value: string): void
  movies: Movie[]
  // ...
}
const movieContext = createContext<MovieContextType>({ /* ... */ })

const MovieApp: React.FC = ({children}) => // ...

// etc.
  • Related