onizukaek
onizukaek

Reputation: 1243

Passing object in props, reactjs with typescript

I'm beginning with ReactJS, and I decided to make my project using typescript. It's an app that fetches movies from an API and displays it.

Here's the app:

import React from 'react';
import '../../assets/css/App.css';
import { Thumb } from '../../components/Thumb';


interface State {
  isLoaded: boolean;
  items: any[];
  error: string;
}
class App extends React.Component<{}, State> {

  state: Readonly<State> = {
    isLoaded: false,
    items: [],
    error: ''
  }

  renderThumbsContainer() {

    const movies = [
      {title: 'Terminator', original_title: 'Terminator', original_language: 'EN', overview: 'A killer robot from future blablabla...', poster_path:'/terminator.jpg'}
    ];

    const thumbs = movies.map((movie, index) => {
      return (
        <Thumb 
          key={index}
          movie={movie}
        />
      );
    });
    return (<div>{thumbs}</div>)
  }

  render() {

    return (
      <div className="App">
        <header className="App-header">
          <h1>Movies</h1>
        </header>
        <main>
          {this.renderThumbsContainer()}
        </main>
      </div>
    );
  }

}

export default App;

And the component displaying the movie details:

import React from 'react';

export function Thumb({ movie: props }: any) {
    return (
        <div className="thumb">
            <div>{props.title}</div>
            <div>{props.original_title}</div>
            <div>{props.original_language}</div>
            <div>{props.overview}</div>
            <div>{props.poster_path}</div>
        </div>
    );
}

After spending 2 hours fighting with the issue of passing an object through props, I finally figured it out using this parameter in the Thumb component function

Thumb({ movie: props }: any)

I thought that the props parameter so Thumb(props: any) should be enough, but datas where not displayed and I finally came up with this, but I just don't understand how this works. First I displayed movie. in the divs, still didn't work and then it worked using props.

I've a lack of knowledge in typescript, for me I declared an object of type any containing a movie attribute of type props as a parameter but it makes no sense.

So I'd like to understand this, did I bind the movie attribute coming from the parent to props or something? Please explain.

Upvotes: 2

Views: 3991

Answers (1)

Gustav
Gustav

Reputation: 557

You can see the JSX <Thumb key={index} movie={movie}/> as syntactic sugar for the function call Thumb(props) where props={key: index, movie: movie}. All your props provided in the JSX element get represented as keys and values on the props object passed to your component.

When you then do function Thumb({ movie: props }), you're destructuring the props argument, essentially taking only the movie key from the now-destructured propsargument and renaming it to "props".

I think you could try something like this instead

import React from 'react';

interface ThumbProps {
  key: number;
  movie: {
    title: string;
    original_title: string;
    // etc...
    }
}

export function Thumb({ movie }: ThumbProps) {
    return (
        <div className="thumb">
            <div>{movie.title}</div>
            <div>{movie.original_title}</div>
            <div>{movie.original_language}</div>
            <div>{movie.overview}</div>
            <div>{movie.poster_path}</div>
        </div>
    );
}

Note: function Thumb({ movie }: ThumbProps) now means that Typescript will expect the destructured propery movie to be of the type defined by the interface ThumbProps`.

Upvotes: 5

Related Questions