Passing data to a component
Let's take a look at the App component we've created earlier:
1
const App: React.FC = () => {
2
const product = {
3
name: "JavaScript: The Definitive Guide",
4
description: `Since 1996, JavaScript: The Definitive Guide...`,
5
price: 28.89
6
}
7
8
return (
9
<section>
10
<h1>Hello DevMeetings!</h1>
11
12
<div>
13
<header>{product.name}</header>
14
<p>
15
{product.description}
16
</p>
17
<span>{product.price}$</span>
18
</div>
19
</section>
20
)
21
}
Copied!
It's simple, but there is still some complexity:
  • some (primitive) state inside,
  • title displayed
  • product displayed
First target for extraction should be the code that is responsible for displaying a product.

The product component

After some copy-pasting, here's the extracted SingleProduct component:
1
const SingleProduct: React.FC = () => {
2
return (
3
<div>
4
<header>{ product.name }</header>
5
<p>
6
{ product.description }
7
</p>
8
<span>{ product.price }$</span>
9
</div>
10
)
11
}
Copied!
The problem here is of course that the product variable is in the App component and undefined in the SingleProduct component. We need to be able to pass data from a parent (App) to the child (SingleProduct). If we were talking about functions, and not components it would look more or less like that:
1
function SingleProduct(product: Product) {
2
return /* ... */
3
}
4
5
function App() {
6
const product = { /* ... */ };
7
8
return SingleProduct(product);
9
}
Copied!
This illustrates the idea: we want to be able to pass arguments to the SingleProduct function.
1
function App() {
2
const product = { /* ... */ };
3
4
return <SingleProduct product={product}/>;
5
}
Copied!

Props

The proper way of passing data down the component tree (from parent to child) is through props. They embody the same concept as function above, just use different syntax:
1
<Component foo={42} bar={"Hello, Devmeetings"} />
Copied!
That's it - we just passed two pieces of data into the Component: foo that is equal to 42, and bar: the string "Hello, Devmeetings".
Let's get back to the function analogy for a second. Defining it like this would make no sense:
1
function Component(foo: number, bar: string) {
2
/* ... */
3
}
Copied!
In this case we are entirely depended on the order of arguments, and their names don't matter event though we typed them. This is much better:
1
function Component(props: { foo: number; bar: string; }) {
2
/* ... */
3
}
Copied!

Component with props

This is exactly what happens in React:
1
const SingleProduct: React.FC = (props: { product: Product }) => {
2
return (
3
<div>
4
<header>{ props.product.name }</header>
5
<p>
6
{ props.product.description }
7
</p>
8
<span>{ props.product.price }$</span>
9
</div>
10
)
11
}
Copied!
We can even improve the component's code, so it's easier to use:
1
export type SingleProductProps = { product: Product };
2
3
const SingleProduct: React.FC<SingleProductProps> = ({ product }) => {
4
return (
5
<div>
6
<header>{ product.name }</header>
7
<p>
8
{ product.description }
9
</p>
10
<span>{ product.price }$</span>
11
</div>
12
)
13
}
Copied!
Much better! With couple of simple changes, we gained:
  • understanding that the React.FC is a generic type we got better type safety and IDE support,
  • by destructuring the props argument simplifies code inside the component,
  • by extracting the SingleProductProps into a type we got a minimalistic documentation

Resources