Callback function in React JS

In this article, we will teach you how you can use a callback function to be called from child parent that will invoke a function in parent component in React JS.

Let’s say you have:

  • A parent component that has an array.
  • You are looping through an array and displaying the data using child component.
  • You want to call a function from child component that will invoke a function in parent component.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<html>
    <head>
        <script src="js/babel.min.js"></script>
        <script src="js/react.development.js"></script>
        <script src="js/react-dom.development.js"></script>
 
        <script type="text/babel" src="js/SingleData.js"></script>
    </head>
 
    <body>
        <div id="app"></div>
 
        <script type="text/babel">
            function App() {
 
                const [data, setData] = React.useState([{
                    id: 1,
                    name: "Adnan",
                    age: 31
                }, {
                    id: 2,
                    name: "Afzal",
                    age: 65
                }, {
                    id: 3,
                    name: "Ali",
                    age: 43
                }]);
 
                return (
                    <>
                        { data.map(function (d, index) {
                            return (
                                <SingleData key={ `data-${ d.id }` }
                                    d={ d } />
                            );
                        }) }
                    </>
                );
            }
 
            ReactDOM.createRoot(
                document.getElementById("app")
            ).render(<App />);
        </script>
    </body>
</html>

Here, we have a React parent component that has an array of data. Each array element has an ID, name and age. You might be receiving this data from API. In each loop iteration, it is rendering a child component.

  • key: This is used by React JS to uniquely identify an element.
  • d: This is the property value parent component is sending to the child component.

What are props in React JS ?

props (properties): Props are used in React JS to pass the data from parent component to child component. They are read-only so child component cannot modify the value of “d”.

Our child component will look like this:

1
2
3
4
5
6
7
8
9
10
11
// js/SingleData.js
 
function SingleData({ d }) {
    return (
        <div>
            <p>
                { d.id } - { d.name } { d.age }
            </p>
        </div>
    );
}

Callback function

Now, let’s assume you want to have a delete function in child component that, when called, will call a function in parent component. So that the parent component that perform an action on that child. In this case, we will remove that array element from “data” array in parent component.

So first, we will create a delete button in child parent. Once that button is clicked, we will call a function we will receive in props from parent component.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// js/SingleData.js
 
function SingleData({ d, onDelete }) {
    return (
        <div>
            <p>
                { d.id } - { d.name } { d.age }
            </p>
 
            <button type="button"
                onClick={ function () {
                    onDelete(d.id);
                } }>Delete</button>
        </div>
    );
}

Now, in our parent component, we need to pass this function as an argument to the child component.

1
2
3
<SingleData key={ `data-${ d.id }` }
    d={ d }
    onDelete={ onDelete } />

Finally, we will create that function in parent component that will search the array element using ID and remove it from array. At the end, we will update the React state variable as well.

1
2
3
4
5
6
7
8
9
10
11
function onDelete(id) {
    const tempArr = [ ...data ];
    for (let a = 0; a < tempArr.length; a++) {
        if (tempArr[a].id == id) {
            tempArr.splice(a, 1);
            break;
        }
    }
 
    setData(tempArr);
}

Here is the complete code of this tutorial.

Parent component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<html>
    <head>
        <script src="js/babel.min.js"></script>
        <script src="js/react.development.js"></script>
        <script src="js/react-dom.development.js"></script>
 
        <script type="text/babel" src="js/SingleData.js"></script>
    </head>
 
    <body>
        <div id="app"></div>
 
        <script type="text/babel">
            function App() {
 
                const [data, setData] = React.useState([{
                    id: 1,
                    name: "Adnan",
                    age: 31
                }, {
                    id: 2,
                    name: "Afzal",
                    age: 65
                }, {
                    id: 3,
                    name: "Ali",
                    age: 43
                }]);
 
                function onDelete(id) {
                    const tempArr = [ ...data ];
                    for (let a = 0; a < tempArr.length; a++) {
                        if (tempArr[a].id == id) {
                            tempArr.splice(a, 1);
                            break;
                        }
                    }
 
                    setData(tempArr);
                }
 
                return (
                    <>
                        { data.map(function (d, index) {
                            return (
                                <SingleData key={ `data-${ d.id }` }
                                    d={ d }
                                    onDelete={ onDelete } />
                            );
                        }) }
                    </>
                );
            }
 
            ReactDOM.createRoot(
                document.getElementById("app")
            ).render(<App />);
        </script>
    </body>
</html>

Child component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function SingleData({ d, onDelete }) {
    return (
        <div>
            <p>
                { d.id } - { d.name } { d.age }
            </p>
 
            <button type="button"
                onClick={ function () {
                    onDelete(d.id);
                } }>Delete</button>
        </div>
    );
}

We used this method in one of our project “Multi-purpose platform in Node JS and Mongo DB“. You can check this out if you want to get a practically view of it.

That is how you can use a callback function in React JS that will invoke a function from child component to parent component.

Practical difference between async await and callback

In one of our tutorial, we learned how to create a function in async await and how to create a function that uses callback.

Video tutorial:

Asynchronous

Let’s say you want to send an email to a user. Following is a Node JS code that sends an email using a callback:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const transport = nodemailer.createTransport({
    host: "",
    port: 465,
    secure: true,
    auth: {
        user: "",
        pass: ""
    }
})
 
transport.sendMail({
    from: "support@adnan-tech.com",
    to: "",
    subject: "Test",
    text: "Hello",
    html: "Hello"
}, function (error, info) {
    console.log("Mail sent: " + (new Date()))
})
 
console.log("I am called: " + (new Date()))

In your terminal, you will see that the “I am called:” message will be displayed instantly. But the “Mail sent:” message will be shown after a few seconds, once the mail is sent. It means that all lines of your code are executed at once, irrespective of the fact that the sendMail function will take some. The code is executed without waiting for any function to complete. This is asynchronous programming.

Synchronous

This can be converted into a synchronous function. Following is the synchronous version of the above code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// the function must be async if await is used inside it
 
app.get("/sendMail", async function (request, result) {
 
    // send an email using a callback
    const transport = nodemailer.createTransport({
        host: "",
        port: 465,
        secure: true,
        auth: {
            user: "",
            pass: ""
        }
    })
 
    const info = await transport.sendMail({
        from: "support@adnan-tech.com",
        to: "",
        subject: "Test",
        text: "Hello",
        html: "Hello"
    })
 
    console.log("Mail sent: " + (new Date()))
 
    console.log("I am called: " + (new Date()))
 
    result.send("")
})

If you run the code now, you will have to wait for the sendMail function to finish before you see your log messages. This is synchronous programming.

Now you have understood the difference, let’s discuss where you should use async await and where you should use a callback.

When to use async await

You should use the async await pattern when the next line of your code is dependent on the previous lines. For example, “you have to insert the record in the database only if the mail is sent successfully”. In this case, you must use async await so that your code will wait for the mail to be sent successfully, then it will insert it in the database.

When to use callback

A callback will be helpful when your code sections are independent of each other. For example, “send an email to the user and insert the record in the database.” In this case, your insertion query should not have to wait for the mail to be sent. The mail should be handled in a callback.