JSFiddle - React, Tailwind, and code Playground

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" >
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

<div class="form-group p-3 border p-2 rounded m-3">
    <div class="row">
        <div class="col-sm-3 text-center pt-2 border-right">
            <label for="mainImage"><img src="http://catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png" alt="Placeholder" id="serviceImage" class="placeholder img-thumbnail" aria-describedby="imagePreviewHelp" /></label>
            <small id="imagePreviewHelp" class="form-text text-muted">Preview could appear stretched</small>
        </div>
        <div class="col">
            <label for="mainImage">Image</label>
            <div class="input-group mb-3">
                <input type="file" class="form-control border p-1" id="mainImage" name="mainImage" />
                <div class="input-group-append">
                    <span class="input-group-text bg-warning text-danger pointer" id="clearUpload">X</span>
                </div>
            </div>
            <div class="input-group mb-3">
                <input type="text" class="form-control" id="imgExt" name="mainImgExt" placeholder="Externel Image" aria-describedby="imageHelp" />
                <div class="input-group-append">
                    <span class="input-group-text bg-warning text-danger pointer" id="clearUploadExt">X</span>
                </div>
            </div>
            <small id="imageHelp" class="form-text text-muted">Upload a local image <strong>or</strong> link to an external image.</small>
        </div>
    </div>
</div>

CSS

pointer {
	cursor: pointer;
}

img.placeholder {
	width: 100px;
	height: 100px;
}

JavaScript

function uploadPreview(input)
{
    if (input.files && input.files[0])
    {
        var reader = new FileReader();
        
        reader.onload = function (e)
        {
            if(e.target.result.trim().length == 0)
            {
                $('#serviceImage').attr('src', 'http://catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png');
            }
            else
            {
                $('#serviceImage').attr('src', e.target.result);
            }
        }
        
        reader.readAsDataURL(input.files[0]);
    }
}

function uploadPreviewExt(input)
{
    if(input.trim().length == 0)
    {
        var previewSrc = '{{CSS_URL}}/images/placeholder.jpg';
    }
    else
    {
        var previewSrc = input;
    }
    
    $('#serviceImage').attr('src', previewSrc);
}

function resetUploadPreview()
{
    if(!$('#previousImage').val())
    {
        $('#serviceImage').attr('src', 'http://catawbabrewing.com/wp-content/themes/catawba/images/placeholder.png');
    }
    else
    {
        $('#serviceImage').attr('src', '{{PROD_IMG}}/' . $('#previousImage').val());
    }
}

$("#mainImage").change(function()
{
    uploadPreview(this);
});

$('[name="mainImgExt"]').on('change', function()
{
    uploadPreviewExt(this.value);
});

$('#clearUpload').on('click', function()
{
    $('#mainImage').val('');
    
    if($('#imgExt').val().trim().length == 0)
    {
        resetUploadPreview();
    }
    else
    {
        uploadPreviewExt($('#imgExt').val());
    }
});

$('#clearUploadExt').on('click', function()
{
    $('#imgExt').val('');
    
    if(!$('#mainImage').val())
    {
        resetUploadPreview();
    }
    else
    {
        uploadPreview($('#mainImage'));
    }
});