React Props
Complex and dynamic interface contains nested components, but it creates new challenge, communication between these components. Props are the means by which one component provides data to another or share data between components.
Props is short for properties. React elements are technically objects which have properties attached with them. These properties contain data available to use in the component.
React has one way data flow model. React enforces a chain of command in which properties have to flow down from a parent component to an immediate child component. Data in React apps only flows down through an app, from parent components to children components. This means you can't skip a layer of children when sending a property. React does not have two way data binding. This also means your children can't send a property back up to a parent.
To pass a name, physics, chemistry and biology from App component to the Student component and render that name, physics, chemistry and biology in the browser. To specify props for a component we specify them as attributes. To specify a name property we simply add the name attribute and to that attribute we assign the value let's go with the name John. Similary add other three attributes.
import React from "react";
import Student from "./Student";
import "./App.css";
function App() {
return <Student name="John" physics="75" chemistry="71" biology="78" />;
}
export default App;
Props are defined by adding properties to the custom HTML elements that apply components. We have defined four props, name, physics... for Student component.
To retrieve these values in the Student component that is a quick two-step process the first step add a parameter to the functional component you are going to call it props you can actually name this anything you want to but the convention is to name it props and I highly recommend you don't deviate from this. Second step is to receive each value use prop.name, prop.physics and so on ...
import React from "react";
export function Student(props) {
return (
<div>
<h1>{props.name}</h1>
<ul>
<li>{props.physics}</li>
<li>{props.chemistry}</li>
<li>{props.biology}</li>
</ul>
</div>
);
}
export default Student;
To receive data in class component we can use this keyword as shown below:
import React, { Component } from "react";
class Student extends React.Component {
render() {
return (
<div>
<h1>{this.props.name}</h1>
<ul>
<li>{this.props.physics}</li>
<li>{this.props.chemistry}</li>
<li>{this.props.biology}</li>
</ul>
</div>
);
}
}
export default Student;
Components can use the JavaScript if..else condition to inspect a prop and render different content based on different conditions.
import React from "react";
export function Student(props) {
if (props.physics > 60 && props.chemistry > 60 && props.biology > 60) {
return <h2>Grade A</h2>;
} else {
return <h2>Grade B</h2>;
}
}
export default Student;
Parent Component
import React from "react";
import Student from "./Student";
import "./App.css";
function App() {
return <Student name="John" marks={[70, 75, 79, 81, 80]} />;
}
export default App;
Child Component
import React from "react";
function marksList(marks) {
let arrayElems = [];
for (let i = 0; i < marks.length; i++) {
arrayElems.push(<li>{`${marks[i]}`}</li>);
}
return arrayElems;
}
export function Student(props) {
return <ul>{marksList(props.marks)}</ul>;
}
export default Student;
The marksList function uses a JavaScript for loop to enumerate the contents of the marks array and adds a li element to a result array.
Child Component
import React from "react";
export function Student(props) {
return (
<ul>
{props.marks.map(mark => (
<li key={mark}>{`${mark}`}</li>
))}
</ul>
);
}
export default Student;
We can use the map method to transform objects in an array into HTML elements. The argument to the map method is a function that is invoked for each object in the array.
Sometimes it is also possible that you might not have an idea as to what content is being passed in but we want the component to render that unknown content we can do that by specifying the content between the opening and closing tag of the parent component and retrieving it using the reserved children property in the props object.
Parent Component
import React from "react";
import Student from "./Student";
function App() {
return (
<Student name="John">
<p>
John is primarily a person enrolled in a school or other educational
institution.
</p>
</Student>
);
}
export default App;
Child Component
import React from "react";
export function Student(props) {
return (
<div>
<h1>{props.name}</h1>
<p>{props.children}</p>
</div>
);
}
export default Student;
React also supports function props, where the parent component provides a child with a function that it can invoke to notify the parent that something important has happened. The parent component can respond by changing the value of the data props, which will trigger an update and allow the child to present updated content to the user.
Parent Component
import React from "react";
import Student from "./Student";
import ReactDOM from "react-dom";
var names = ["John", "Alice", "Mark"];
function userName(name) {
names = names.filter(item => item !== name)
ReactDOM.render(<App />, document.getElementById("root"));
}
export default function App() {
return (
<ul>
{names.map((name, index) => (
<li key={name}>
<Student index={index} name={name} userCallback={userName} />
</li>
))}
</ul>
);
}
Child Component
import React from "react";
export function Student(props) {
return (
<React.Fragment>
<span>{props.name}</span>
<span>
<button onClick={() => props.userCallback(props.name)}>
Click Here
</button>
</span>
</React.Fragment>
);
}
export default Student;
The function defined as userName, uses the JavaScript method to remove the item from array. The userName function is provided to the Student component as the value for a prop named userCallback. The onClick expression is a fat arrow function that calls the function prop when it is invoked.
For performance reasons, we want to avoid passing props down through too many layers of components if it is not necessary. There are some instances when we might want to pass all or most of the props from one component into a child. We can use the JavaScript Spread operator to help with this.
src\App.js [Parent]
import React from "react";
import Student from "./Student";
import "./App.css";
function App() {
return (
<div>
<Student name="Mathew" physics="45" chemistry="49" biology="53" />
<Student name="John" physics="75" chemistry="71" biology="78" />
<Student name="Robin" physics="95" chemistry="91" biology="88" />
</div>
);
}
export default App;
src\Student.js [First Level Child]
import React from "react";
import Marks from "./Marks";
export function Student(props) {
return (
<div>
<h1>{props.name}</h1>
<Marks {...props} />
</div>
);
}
export default Student;
src\Marks.js [Second Level Child]
import React from "react";
export function Marks(props) {
return (
<div>
<ul>
<li>{props.physics}</li>
<li>{props.chemistry}</li>
<li>{props.biology}</li>
</ul>
</div>
);
}
export default Marks;
The {...props} expression passes on all of the props received from the parent component.