MrVoland
MrVoland

Reputation: 283

React Typescript passing props and data type

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

  1. What will be the { data } type? How to define it?
  2. How to pass the functions as props to the Results.tsx file? How define result, results and openPopup in this function?
  3. Did I miss something else?

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

Answers (1)

Linda Paiste
Linda Paiste

Reputation: 42188

Prop Types

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 }) => {

Data Type

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

Related Questions