What are props?
Consider a function in any programming language. How do we pass values to the function? Using parameters. Props (properties) are similar to parameters. They are used to pass data from one component to another in React. Below is the simplest example on how to pass props:
const Banner = props => {
const name = props.name
return <div>Hello {name}</div>
}
function App() {
return (
<div>
<Banner name="Abhishek" />
</div>
)
}
export default App
A couple of things you need to be aware of props are:
- Props are read-only, they should not be mutated.
- We cannot pass props from a child component to a parent component. Props always move from top to bottom in the component hierarchy.
Passing functions as Props
We can pass functions as props as well:
const Banner = props => {
const name = props.name
return (
<div>
<p>Hello {name}</p>
<button onClick={props.clickHandler}>Click Me</button>
</div>
)
}
function App() {
const showAlert = () => {
alert("Welcome!")
}
return (
<div>
<Banner name="Abhishek" clickHandler={showAlert} />
</div>
)
}
export default App
As you could see (line 17), the name of the function and the prop need not be the same.
Passing Boolean values
If you specify a prop without any values, it will be treated as a Boolean with value true
:
const Banner = props => {
const name = props.name
return <div>{props.show && <p>Hello {name}</p>}</div>
}
function App() {
return (
<div>
<Banner name="Abhishek" show />
</div>
)
}
export default App
If you need to pass false
, then you need to explicitly mention it like:
<Banner name="Abhishek" show={false} />
Passing a state as a prop
You can pass the parent component state as a prop to the child component:
import { useState } from "react"
const Banner = props => {
const name = props.name
return (
<div>
<p>
{props.greeting} {name}
</p>
</div>
)
}
function App() {
const [greeting, setGreeting] = useState("Hello")
return (
<div>
<Banner name="Abhishek" greeting={greeting} />
</div>
)
}
export default App
Also, you can modify the parent state by passing a function to the child component as follows
import { useState } from "react"
const Banner = props => {
const name = props.name
return (
<div>
<p>
{props.greeting} {name}
</p>
<button onClick={props.changeGreeting}>Change greeting</button>
</div>
)
}
function App() {
const [greeting, setGreeting] = useState("Hello")
const changeGreeting = () => {
setGreeting("Howdy")
}
return (
<div>
<Banner
name="Abhishek"
greeting={greeting}
changeGreeting={changeGreeting}
/>
</div>
)
}
export default App
Here we are passing the changeGreeting
function as a prop to the Banner component, and calling it from the Banner component when the button is clicked. Inside the changeGreeting
function, we are modifying the state to 'Howdy'.
Passing objects as Props
Consider the following example:
const UserCard = props => {
const name = props.user.name
const role = props.user.role
const age = props.user.age
const profilePic = props.user.profilePic
return (
<div>
<p>Name: {name}</p>
<p>Role: {role}</p>
<p>Age: {age}</p>
<img src={profilePic} alt={name} />
</div>
)
}
function App() {
const user = {
name: "Abhishek",
role: "Software Engineer",
age: 27,
profilePic: "image.jpg",
}
return (
<div>
<UserCard user={user} />
</div>
)
}
export default App
Here we are passing an object to the child component and accessing it like props.user.name
. So every time we need to access a property, we need to dig through props.user
.
This can be avoided by passing them as individual props as shown below:
const UserCard = props => {
const name = props.name
const role = props.role
const age = props.age
const profilePic = props.profilePic
return (
<div>
<p>Name: {name}</p>
<p>Role: {role}</p>
<p>Age: {age}</p>
<img src={profilePic} alt={name} />
</div>
)
}
function App() {
const user = {
name: "Abhishek",
role: "Software Engineer",
age: 27,
profilePic: "image.jpg",
}
return (
<div>
<UserCard
name={user.name}
role={user.role}
age={user.age}
profilePic={user.profilePic}
/>
</div>
)
}
export default App
Still we haven't solved the need to write user.
for accessing every prop.
We just elevated it to parent component.
This syntax can be simplified further using Javascript spread operator
const UserCard = props => {
const name = props.name
const role = props.role
const age = props.age
const profilePic = props.profilePic
return (
<div>
<p>Name: {name}</p>
<p>Role: {role}</p>
<p>Age: {age}</p>
<img src={profilePic} alt={name} />
</div>
)
}
function App() {
const user = {
name: "Abhishek",
role: "Software Engineer",
age: 27,
profilePic: "image.jpg",
}
return (
<div>
<UserCard {...user} />
</div>
)
}
export default App
The only change is in line number 26, where instead of passing individual props, we have just passed {...props}
.
Destructuring props
If you see the above example, in the child component, we are using props.name
, props.age
etc for accessing the props.
Can we simplify this further? Yes, we can.
const UserCard = ({ name, role, age, profilePic }) => {
return (
<div>
<p>Name: {name}</p>
<p>Role: {role}</p>
<p>Age: {age}</p>
<img src={profilePic} alt={name} />
</div>
)
}
function App() {
const user = {
name: "Abhishek",
role: "Software Engineer",
age: 27,
profilePic: "image.jpg",
}
return (
<div>
<UserCard {...user} />
</div>
)
}
export default App
As you may observe, we have used JavaScript destructing to access the props directly.
These are just different ways to pass an object to the child component.
There is no such thing as the best practice.
You may use a style of your choice.
Default props
What if the parent component misses passing a prop? How to make sure our code does not break and there is always a fallback value? We can use default props for that.
Default props can be set using different ways.
Using Short circuit evaluation
We can use the logical OR operator to set a default name as shown below:
const Banner = props => {
const name = props.name || "user"
return <div>Hello {name}</div>
}
function App() {
return (
<div>
<Banner />
</div>
)
}
export default App
Using default parameters
We can also specify a default parameter while destructing the props:
const Banner = ({ name = "user" }) => {
return <div>Hello {name}</div>
}
function App() {
return (
<div>
<Banner />
</div>
)
}
export default App
Using defaultProps
There is another way to explicitly specify the default props in React.This is the most recommended approach:
const Banner = ({ name }) => {
return <div>Hello {name}</div>
}
function App() {
return (
<div>
<Banner />
</div>
)
}
Banner.defaultProps = {
name: "user",
}
export default App
Also, you can validate the type of the props using prop-types
Renaming props
If you would like to change the name of the prop, then you can do so as shown below:
const UserCard = ({ name, role: occupation }) => {
return (
<div>
<p>Name: {name}</p>
<p>Occupation: {occupation}</p>
</div>
)
}
function App() {
return (
<div>
<UserCard name="Abhi" role="Software Engineer" />
</div>
)
}
export default App
Here we are passing a prop called role
from the parent component, which we are renaming to occupation
in the child component.
Passing components as children
We can pass a component to another component by wrapping it within the parent component as shown below:
const UserCard = ({ name, children }) => {
return (
<div>
<p>Name: {name}</p>
{children}
</div>
)
}
const UserIcon = ({ profilePic }) => {
return <img src={profilePic} alt="profile" />
}
function App() {
return (
<div>
<UserCard name="Abhi">
<UserIcon profilePic="image.jpg" />
</UserCard>
</div>
)
}
export default App
As you may see, we can access the passed component using children
prop.
An alternate way to pass a component to the child is using a named prop as shown below:
const UserCard = ({ name, icon }) => {
return (
<div>
<p>Name: {name}</p>
{icon}
</div>
)
}
const UserIcon = ({ profilePic }) => {
return <img src={profilePic} alt="profile" />
}
function App() {
return (
<div>
<UserCard
name="Abhi"
icon={<UserIcon profilePic="image.jpg" />}
></UserCard>
</div>
)
}
export default App
Hope you have liked the article and have a clear understanding of different ways of passing props in React. Do let me know in the comments below if you have any questions.
Top comments (1)
excellent bro