I am making an application that renders Gifs (from the Giphy API) with React and TypeScript and it is giving me a problem when outsourcing the service to an external file to leave the code cleaner. Let's look at the following components of my application.
GifGridItem.tsx
(it simply returns each Gif already to show in the app):
import React, { useState } from "react";
import { GifsInterface } from "./GifGrid";
import "../index.css";
function GifGridItem(props: GifsInterface) {
const { id, title, url } = props;
return (
<div className="card">
<img src={url} alt={title} />
<p>{title}</p>
</div>
);
}
export default GifGridItem;
GifGrid.tsx
(renders you the list of gifs):
import React, { useState, useEffect } from "react";
import GifGridItem from "./GifGridItem";
import "../index.css";
import { getGifs } from "../helpers/getGifs";
export interface GifGridProps {
information: string;
}
export interface GifsInterface {
id?: string;
title?: string;
url?: string;
}
function GifGrid(props: GifGridProps): JSX.Element {
const { information } = props;
const [images, setImages] = useState<GifsInterface[]>([]);
useEffect(() => {
getGifs(information).then(setImages);
}, []);
return (
<>
<h3>{information}</h3>
<div className="card-grid">
{images.map((img) => (
<GifGridItem key={img.id} title={img.title} url={img.url} />
))}
</div>
</>
);
}
export default GifGrid;
GetGifs.tsx
(file where I make the API call).
import { GifGridProps } from "../components/GifGrid";
export const getGifs = async (props: GifGridProps) => {
const { information } = props;
const url = `https://api.giphy.com/v1/gifs/search?api_key=${api_key}&q=${encodeURI(
information
)}&limit=10`;
const resp = await fetch(url);
const { data } = await resp.json();
const gifs = data.map((img: any) => {
return {
id: img.id,
title: img.title,
url: img.images?.downsized_medium.url,
};
});
return gifs;
};
I also have the component AddCategory.tsx
, which allows you to add a new keyword so that the app's logic ends up calling the API using that keyword.
import React, { useState } from "react";
import { InformationProps } from "../interfaces";
function AddCategory({ setInformation }: InformationProps) {
const [inputValue, setInputValue] = useState<string>("");
const handleInputChange = (e: any) => {
setInputValue(e.target.value);
};
const handleSubmit = (e: any) => {
e.preventDefault(); //It avoids the page to load again when the form is submitted
if (inputValue.trim().length > 2) {
//In order to avoid insert elements without text
setInformation((information: string[]) => [inputValue, ...information]);
setInputValue(" "); //Cleaning the textbar
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
onChange={handleInputChange}
className="textBar"
value={inputValue}
/>
</form>
);
}
export default AddCategory;
And finally I have GifExpertApp.tsx
:
import React, { useState } from "react";
import AddCategory from "./components/AddCategory";
import GifGrid from "./components/GifGrid";
function GifExpertApp() {
const [information, setInformation] = useState<string[]>([""]);
return (
<div className="App">
<header className="App-header">
<h1>Gif Expert App</h1>
<AddCategory setInformation={setInformation} />
<hr />
<ol>
{information.map((information) => {
return <GifGrid key={information} information={information} />;
})}
</ol>
</header>
</div>
);
}
export default GifExpertApp;
I have shared all the code because I don't know due to shipping props with TypeScript to what extent it was important to share all the code. In summary, my problem is that in the file GifGrid.tsx
, in this piece of code:
useEffect(() => {
getGifs(information).then(setImages);
}, []);
I get an error in information
, since it tells me that Argument of type 'string' is not assignable to parameter of type 'GifGridProps'
. However, I don't understand it, since precisely that interface only has one variable which is information
and which, precisely, is of type String
. Could someone point me to what I'm doing wrong? Thank you very much :)