Reputation: 283
I'm still pretty new into the world of TypeScript and I have a couple of questions. I have a few errors in my code, and I'm not rlly sure how to pass the props and choose the right type. I would appreciate a bit of help on that one.
Do you have maybe a good source where I can find all the necessary React info in one place just for the start?
tl;dr
App.tsx
import React, { useState } from 'react'
import axios from 'axios'
import Search from './components/Search'
import Results from './components/Results'
import Popup from './components/Popup'
export type selected = {
Title?: string,
Year?:number
}
type values = {
s: string,
results: string[],
selected: selected,
}
interface popup {
id: string
}
const App: React.FC = () => {
const [state, setState] = useState<values>({
s: "",
results: [],
selected: {}
});
const apiurl = "http://www.omdbapi.com/?apikey=dfe6d885";
const search = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
axios(apiurl + "&s=" + state.s).then(({ data }) => {
let results = data.Search;
setState(prevState => {
return { ...prevState, results: results }
})
});
}
}
const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {
let s = e.target.value;
setState(prevState => {
return { ...prevState, s: s }
});
}
const openPopup = (id : string) => {
axios(apiurl + "&i=" + id).then(({ data }) => {
let result = data;
console.log(result);
setState(prevState => {
return { ...prevState, selected: result }
});
});
}
const closePopup = () => {
setState(prevState => {
return { ...prevState, selected: {} }
});
}
return (
<div className="App">
<header>
<h1>Movie Database</h1>
</header>
<main>
<Search handleInput={handleInput} search={search} />
<Results results={state.results} openPopup={openPopup} />
{(typeof state.selected.Title != "undefined") ? <Popup selected={state.selected} closePopup={closePopup} /> : false}
</main>
</div>
);
}
export default App
Results.tsx
import React from 'react'
import Result from './Result'
function Results ({ results, openPopup }) {
return (
<section className="results">
{results.map(result => (
<Result key={result.imdbID} result={result} openPopup={openPopup} />
))}
</section>
)
}
export default Results
Upvotes: 4
Views: 17374
Reputation: 42188
You can defined the props that you pass to a function component inline
function Results ({ results, openPopup }: { results: MyResult[], openPopup: () => void }) {
But it's more common to define a separate interface
for the props
interface Props {
results: MyResult[];
openPopup: () => void;
}
Which you can use to define the props directly
function Results ({ results, openPopup }: Props) {
Or through React.FC
const Results: React.FC<Props> = ({ results, openPopup }) => {
To define the type for data
you need to create an interface
that has all of the properties in the API response that you want to use. Then when you call axios
, you use the generic type of the axios
function to tell it what the fetched data should look like.
For whatever reason, axios()
doesn't seem to take a generic, but axios.get()
does.
axios.get<MyApiResponse>(apiurl + "&s=" + state.s).then(({ data }) => {
Now the data
variable automatically has the MyApiResponse
type.
Upvotes: 6