Q:

Unable to understand when a return statement must be used in association with recursion

I was brushing up on the concept of recursion and working with binary trees. I don‘t understand the difference between instances of using a return statement with a recursive call and other times when return is not used. I‘ll give code illustrating my question.
Here is a function that checks if a value is present in a BST:
public boolean containsNodeRecursive(Node current, int value) {
    if (current == null) {
        return false;
    }

    if (value == current.data) {
        return true;
    }

    //HERE, THE RECURSIVE CALL IS PRECEDED BY A RETURN STATEMENT
    return value < current.data
      ? containsNodeRecursive(current.left, value)
      : containsNodeRecursive(current.right, value);
   }
}

Here is a function for insertion of data into a BST:
public Node insert(Node current, int data) {
    if (current == null) {
        return createNode(data);
    } else if (data < current.data) {
        //RECURSIVE CALL HERE WITHOUT USE OF A RETURN STATEMENT
        current.left = insert(current.left, data);
    } else if (data > current.data) {
        current.right = insert(current.right, data);
    }

    return current;
}

I think my question boils down to: “When should we return a recursive call and when should we not?”

A:

There are two types of functions presented, so there are two separate rules we need to follow.
Take the first function you provided:
public boolean containsNodeRecursive(Node current, int value) {
    if (current == null) {
        return false;
    }

    if (value == current.data) {
        return true;
    }

    //HERE, THE RECURSIVE CALL IS PRECEDED BY A RETURN STATEMENT
    return value < current.data
      ? containsNodeRecursive(current.left, value)
      : containsNodeRecursive(current.right, value);
   }
}

This function is intended to find a single target value and return it. In this case, we return a recursive call when we want to return a value that we know will be provided by a single child of the node being tested.
However, take the insertion example:
public Node insert(Node current, int data) {
    if (current == null) {
        return createNode(data);
    } else if (data < current.data) {
        //RECURSIVE CALL HERE WITHOUT USE OF A RETURN STATEMENT
        current.left = insert(current.left, data);
    } else if (data > current.data) {
        current.right = insert(current.right, data);
    }

    return current;
}

This code is intended to accomplish a different type of task. Rather than seeking a single target value, this recursive function is intended to modify the existing tree. In this case, we return only the modifications that we want to make to the existing tree (or the duplicate value).

