Communication between Components and Two way binding in React
React Components are essential building block of any react application. These components can communicate and can share different relationships with each other. Communication between these components essentially links the hierarchy of a react application. In this article, we will be looking at parent-child communication and vice versa. We will also look at two way binding in React.
Let us move forward with a code example. We will create a class component called Blogs which will hold a list of recent posts. We will then pass this data to the child component called Post.
Parent To Child communication in React
This is the most straightforward way of communication between 2 react components. It is the one, which you will end up using in every react application you build. Here, the parent component passes data to the child component when invoking the child component. We then reference this data using props(name could be anything) in the child component. You should use these props as is, and never manipulate(mutate) them.
import Post from './Post';
import Feedback from './Feedback';
import './Blogs.css';
class Blogs extends Component{
state = {
posts: [
{
article: "Two way binding in React",
author: "Moiz"
},
{
article: "Class based and function based components in react",
author: "Moiz"
},
{
article: "Angular Toaster Notification Tutorial",
author: "Rahil"
}
],
feedback: "Enter your feedback"
}
render() {
const post = this.state.posts.map((el, index) => {
return <Post article = {el.article} author = {el.author} key = {index}/>
})
return <div className = "container">
<p>Recent Posts on Ciphertrick</p>
<div>
{post}
</div>
</div>
}
}
export default Blogs;
In the above code, we loop through the data stored inside of state and pass on the data as article and author to the child component i.e Post Component.
import './Post.css';
const Post = (props) => {
return <div className = "postBlock">
<div className = "content">Article: {props.article}</div>
<div className = "content">Author: <b>{props.author}</b></div>
</div>
}
export default Post
Child To Parent Communication in React
Now what if the child wants to communicate back to its parent? The child component can essentially let its parent know about events. In the above Post component, let us add delete a button next to each post. When a user clicks delete, It must remove that article from the list. We will add an onClick event on the child component, and pass a reference from the parent component.
import Post from './Post';
import Feedback from './Feedback';
import './Blogs.css';
class Blogs extends Component{
state = {
posts: [
{
article: "Two way binding in React",
author: "Moiz"
},
{
article: "Class based and function based components in react",
author: "Moiz"
},
{
article: "Angular Toaster Notification Tutorial",
author: "Rahil"
}
],
feedback: "Enter your feedback"
}
onDeletePost = (ind) => {
let currentPost = []
currentPost = this.state.posts.filter((el, index ) => {
return ind !== index
})
this.setState({
posts: currentPost
})
}
render() {
const post = this.state.posts.map((el, index) => {
return <Post article = {el.article} author = {el.author} key = {index}
delete = {() => this.onDeletePost(index)}
/>
})
return <div className = "container">
<p>Recent Posts on Ciphertrick</p>
<div>
{post}
</div>
</div>
}
}
export default Blogs;
Here, we’ve created an onDeletePost() method and have passed its reference as ‘delete’ to the child component. The onDeletePost() uses the index of the array element to delete the appropriate article.
import './Post.css';
const Post = (props) => {
return <div className = "postBlock">
<div className = "content">Article: {props.article}</div>
<div className = "content">Author: <b>{props.author}</b></div>
<button onClick = {props.delete}>Delete</button>
</div>
}
export default Post
Inside the child component, we have attached an onClick event to the button element. Whenever the button is clicked, the event will be received by the parent component which will then execute the onDeletePost() method.
Two Way Binding in React
Till now, we saw how to communicate between parent and child components one at a time. What if we want bi-directional communication simultaneously between the parent and child components?
Well, we will add an input element inside of the new Feedback component, where you can write some text as feedback.
import './Feedback.css';
const Feedback = (props) => {
return <div className = "inputcontainer">
<label>Feedback:
<input
type = "text" name = "feedback"
value = {props.value}
onChange = {props.change}/>
</label>
</div>
}
export default Feedback;
The feedback component consists of an input element where users can type their feedback. An onChange event is attached to the input element, which gets triggered every time the user types some text in it. Inside the class component we use the onFeedbackChange() method to update the contents of the state and pass the data again to the feedback component as props, thus binding both the components.
import Post from './Post';
import Feedback from './Feedback';
import './Blogs.css';
class Blogs extends Component{
state = {
posts: [
{
article: "Two way binding in React",
author: "Moiz"
},
{
article: "Class based and function based components in react",
author: "Moiz"
},
{
article: "Angular Toaster Notification Tutorial",
author: "Rahil"
}
],
feedback: "Enter your feedback"
}
onDeletePost = (ind) => {
let currentPost = []
currentPost = this.state.posts.filter((el, index )=> {
return ind !== index
})
this.setState({
posts: currentPost
})
}
onFeedbackChange = (e) => {
this.setState({feedback: e.target.value})
}
render() {
const post = this.state.posts.map((el, index) => {
return <Post article = {el.article} author = {el.author} key = {index}
delete = {() => this.onDeletePost(index)}
/>
})
return <div className = "container">
<p>Recent Posts on Ciphertrick</p>
<div>
{post}
</div>
<Feedback value = {this.state.feedback} change = {this.onFeedbackChange}/>
</div>
}
}
export default Blogs;
Inside the class component, we are now invoking the Feedback component as well, and passing the state's feedback value to it.
As mentioned earlier the onFeedbackChange() gets executed every time the value in Feedback component’s input element change. The onFeedbackChange() method receives an event and we use its target.value property to get the existing value of the input element. We then set the state’s feedback property to target.value.
In this way, we essentially achieve a two way binding between these two components.
So To Conclude.
The above-mentioned techniques are some of the basic and important ways of communication between a parent and a child component. With that being said, these are not the only ways components can communicate. There are other ways of sharing data like using React’s context API and other third-party libraries like Redux. I’ll be covering these topics in detail in a separate article. If you have any queries, feel free to drop a comment below. The GitHub repo for the above example code https://github.com/Moiz47/react-data-binding.git
The CSS files for the code above.
width: 40%;
margin: 5px auto;
box-sizing: border-box;
box-shadow: 2px 2px 4px #aaaaaa;
}
p{
margin: 0px;
text-align: center;
padding: 10px 0px;
font-size: 18px;
}
width: 80%;
height: 90px;
border: 1px solid black;
margin: 20px auto;
margin-bottom: 20px;
font-size: 15px;
box-sizing: border-box;
}
button{
background-color: white;
border: 1px solid red;
border-radius: 2px;
color: red;
padding: 3px 6px;
margin: 5px 10px;
text-align: center;
font-size: 12px;
float: right;
}
.content{
padding: 3px 5px;
}
margin: 10px 10px;
width: 70%
}
.inputcontainer{
width: 80%;
margin: 10px auto;
text-align: center;
}