DEV Community

Cover image for Understand One-way Data Binding in React the easy way!
Parnika-Gupta
Parnika-Gupta

Posted on • Updated on

Understand One-way Data Binding in React the easy way!

React is a popular JavaScript library for many reasons and one of the reasons is “one-way data binding”. If you want to understand React to its core, you should read along.

It’s a one-way road for the data

React apps are made up of carefully organized components. These components receive arguments(props) and return information using the return value of the render function. When data flows from the parent to the child component, it is known as the unidirectional flow of data.

Parent component passes information to child component using props. But it is also possible that a child component might end up requiring to change something in the UI. What to do in that case?

Is it possible to pass data from the child to parent component?

What if clicking a button in the child component changes the text in the parent component? How do we make sure that the parent component is aware that a button is clicked that is supposed to change its text?

This is achieved by the parent component by passing a callback function as a prop when calling the child component. The child component now calls this function when the button is clicked. This provides the parent component with all the required information about the state of the child component or the user actions.

Example

Before anything else, it is essential to understand which UI component should be changed based on the user input. This is where the concept of “state” comes in.

As we already discussed, we need to change the text in the parent component that is currently “Hello” to “World”. So, that is our element of the state.

Now, which component should the state live in? The child? The parent? Um.. so here are a few steps that would make it easier for you to decide where the state should reside:

  • See which component renders something based on the state.
  • Identify the highest component in the hierarchy that relies on the state.
  • The state lives in either the highest component in the hierarchy or some other higher component.
  • If you are unable to find a component worthy of owning the state, you can create a completely new component whose whole purpose is to hold the state. Then you can add this component as the highest component in the hierarchy.

In our case, it is easy to identify that the state should reside in the “Parent” component.

const [text, setText] = useState(Hello);
Enter fullscreen mode Exit fullscreen mode

Now, what do we do to the “Parent” component? We pass the callback function as a prop from the parent component.

<Child changeText={(text) => setText(text)} />
Enter fullscreen mode Exit fullscreen mode

Now we need a callback function in the “Child” component that is triggered when the button is clicked.

<button onClick={() => props.changeText(World)}>
Enter fullscreen mode Exit fullscreen mode

With all individual elements in place, here is what the JavaScript files look for each component:

Parent.js

import React, { useState } from react;
import Child from ./Child;
function Parent(props) {
const [text, setText] = useState(Hello);
return (
<div>
<h1>{text}</h1>
<Child changeText={(text) => setText(text)} />
</div>
);
}
export default Parent;
Enter fullscreen mode Exit fullscreen mode

Child.js

import React from react;
function Child(props) {
return (
<div>
<button onClick={() => props.changeText(World)}>
Change the text
</button>
</div>
);
}
export default Child;
Enter fullscreen mode Exit fullscreen mode

App.js

import Parent from ./Parent;
function App() {
return (
<>
<div className=App>
<Parent />
</div>
</>
);
}
export default App;
Enter fullscreen mode Exit fullscreen mode

How does it work?

In the “Parent” component, the content inside the heading tag is supposed to change, initially, it is set to “Hello”. Now when the button(in the child component) is clicked, it triggers the onClick event listener that calls the callback function passed from the “Parent” to the “Child” component, which changes the text to “World” and re-renders the component.

Conclusion

React follows the unidirectional approach, meaning that data flows from parent to child and not vice versa but if you really need to manipulate your parent component based on something in the child component, you can use a callback function and pass it as a prop from the parent to child.

This function updates the state in the parent component and once the state is changed, it passes down as props again. This allows the components to re-render and display the required results.

Here I explained passing data from child to parent component using functional components, the same can be achieved using class components as well.

Top comments (29)

Collapse
 
anuraggharat profile image
Anurag Gharat

Hi Parnika. Nice Explanation. But I think the heading is a little misleading. You mentioned about one way data binding in React and the article is about Unidirectional Data flow in React. Both are two different things.

One way data binding happens on the component level. Where the Component UI is connected and synced with the Component state.

While Unidirectional Data flow is about passing data from Higher component to lower component in Component Hierarchy.

Collapse
 
nis6 profile image
Nisha Chauhan

Just what I was looking for! Thanks a lot Anurag!

Collapse
 
salarc123 profile image
SalarC123 • Edited

I’m curious as to why you passed a callback to the child instead of just directly passing the setText function

Collapse
 
parnikagupta profile image
Parnika-Gupta

Hey there is no particular reason I did that. Is there a reason why we should or shouldn't be using arrow functions when we can directly pass the setText function? I would love to learn more about the depth of it.

Collapse
 
permanar profile image
Richie Permana

IMHO, its just matter of simplicity and consistency.

<Child setText={ setText }>
// is the same as
<Child setText={(text) => { setText(text) }}>

// but not as
<Child setText={ setText() }>
//or
<Child setText={(text) => setText(text)}>
Enter fullscreen mode Exit fullscreen mode

CMIIW.

Thread Thread
 
parnikagupta profile image
Parnika-Gupta

I just saw a video on callbacks that made it clear for me.. I will find it again to grab a link and share if anyone needs...But what's the difference between 2nd format and the 4th one that you have shared?

Collapse
 
salarc123 profile image
SalarC123

I’m not actually sure. I’ve just always done it like this, but I don’t really see any differences between the two methods

Collapse
 
rabbimorgan profile image
Rabbi-Morgan

The setText is a useState function, calling in somewhere is won't change the state, you have to call it in it's own component for it to work.
so he is returning the setState with the new value of text from the child to the parent which will now bw executed in the parent.

Collapse
 
dawnind profile image
Mainak Das

For the syntax highlighting add the type after the first three backticks

Collapse
 
parnikagupta profile image
Parnika-Gupta

Thanks Mainak! Will take care of it going forward.

Collapse
 
ptejada profile image
Pablo Tejada

Why there is no syntax highlighting in your code snippets?

Collapse
 
parnikagupta profile image
Parnika-Gupta

Sorry I am new here so I am not familiar with formatting. Will improve in next one for sure!

Collapse
 
hyggedev profile image
Chris Hansen • Edited

Don't be sorry. I'm new too, and barely found out about syntax highlighting! ✌️

PS+
You can totally go back and edit your post and add javascript immediately after your first three back-ticks 😀
Also, awesome article 👋

Thread Thread
 
parnikagupta profile image
Parnika-Gupta • Edited

That's great will go back and do that right away! Thank you so much.

Thread Thread
 
ptejada profile image
Pablo Tejada • Edited

This was the first article without syntax highlighting I saw. I just assume it was something done automatic like on Stackoverflow. I learned about this recently myself.

Thread Thread
 
parnikagupta profile image
Parnika-Gupta

Thanks for pointing it out though! Helped me learn a new thing. :)

Collapse
 
artydev profile image
artydev • Edited

Hello @parnikagupta ,

What do you think of this ? :

Only to see that there is a life outside React :-)

ParentChild

In case you are interested how this works, you can give an eye here : DML




// make : wrapper around createElement
const cType = (type) => (content, props) => make(type, props, content)

const h1 = cType("h1");
const div = cType("div");
const button = cType("button");
const br = () => make("br");


const cssChild= `
  border: 1px solid red; 
  padding:10px;
  background:orange;
  box-shadow: 1px 10px 20px rgba(120,80,0,0.34)
`

function Parent () {
  selectBase(div('', "background:darkorange; padding:10px; margin:10px"))
  h1("Parent")
  let c = Counter();
  br()
  button("inc child counter").onclick = () => c.incby(1);
  unselectBase()
}

function Counter () {
    selectBase(div("I am the child...", cssChild))
      let value = div("0");
      let incby = (val) =>  value.innerText = Number(value.innerText)+val
      button("inc").onclick = () => incby(1);
      button("dec").onclick = () => incby(-1);
    unselectBase()
    return { incby }
}


Parent();
Parent();
Parent()


Enter fullscreen mode Exit fullscreen mode

You can try it here : ParentChild

Regards

Collapse
 
kashyaprahul94 profile image
Rahul Kashyap • Edited

Nicely articulated. Congratulations on your first post.

It is worth to note that this holds good to any level of nesting of the components however not advised :)

Such situations can be dealt beautifully with Contexts or state management libs.

Collapse
 
parnikagupta profile image
Parnika-Gupta

Thank you Rahul! Means a lot. But this is sort of my 2nd post but this one has reached more people, I guess people liked it better than my previous one 😜
Thanks for the additional information I have added it to my knowledge of React now! Really appreciate it.

Collapse
 
parnikagupta profile image
Parnika-Gupta

Ah! Thanks for calling that out I copied the working code from my VS Code but I was deleting some experimental divs I was adding so must have deleted the div closing tag by mistake! I will just correct it in a sec.

Collapse
 
capscode profile image
capscode

wonderful article

Collapse
 
parnikagupta profile image
Parnika-Gupta

Thank You!

Collapse
 
antoniomora95 profile image
Antoniomora95

Simple and useful

Collapse
 
parnikagupta profile image
Parnika-Gupta

Thank you so much!

Collapse
 
alexandrefuente profile image
alexandrefuente

Great article. Thanks @parnikagupta .

Collapse
 
parnikagupta profile image
Parnika-Gupta

Thank you @alexandrefuente means a lot!

Collapse
 
aesthytik profile image
Vipin Kumar Rawat

Nice article!
So does this means, React also supports 2 way data binding? The data component and view component can both change each other?