This is my snippet to display the loss curve in visdom which is working fine.
    vis = visdom.Visdom()
    loss_window = vis.line(X=torch.zeros((1,)).cpu(),
                           Y=torch.zeros((1)).cpu(),
                           opts=dict(xlabel='epoch',
                                     ylabel='Loss',
                                     title='Training Loss',
                                     legend=['Loss']))    
    vis = visdom.Visdom()
    accuracy_window = vis.line(X=torch.zeros((1,)).cpu(),
                           Y=torch.zeros((1)).cpu(),
                           opts=dict(xlabel='epoch',
                                     ylabel='accuracy',
                                     title='Training accuracy',
                                     legend=['accuracy']))    
#    
    for epoch in range(200):  # loop over the dataset multiple times
        
        t0 = time.time()
        
        running_loss = 0
        total_train = 0
        correct_train = 0
        
        model.train()
        for i, data in enumerate(train_loader, 0):
            # get the inputs
            t_image, mask = data
            t_image, mask = Variable(t_image.to(device)), Variable(mask.to(device))
        

            # zeroes the gradient buffers of all parameters
            optimizer.zero_grad()
            # forward + backward + optimize
            outputs = model(t_image) # forward
            loss = criterion(outputs, mask) # calculate the loss
            loss.backward() # back propagation
            optimizer.step() # update gradients
            running_loss += loss.item()
            
            # accuracy
            _, predicted = torch.max(outputs.data, 1)
            total_train += mask.nelement()  # number of pixel in the batch
            correct_train += predicted.eq(mask.data).sum().item() # sum all precited pixel values
            train_accuracy = 100 * correct_train / total_train
           #avg_accuracy = train_accuracy / len(train_loader)                                     
            
            print('Epoch {}, train Loss: {:.3f}'.format(epoch, loss.item()), "Training Accuracy: %d %%" % (train_accuracy), '{:.3f} seconds'.format(time.time() - t0))
            
            
            values = [epoch+1, running_loss, train_accuracy]
            export_history(header, values, save_dir, save_file_name)

            vis.line(
                    X=torch.ones((1, 1)).cpu()*epoch,
                    Y=torch.Tensor([loss]).unsqueeze(0).cpu(),
                    win=loss_window,
                    update='append')
            
            vis.line(
                    X=torch.ones((1, 1)).cpu()*epoch,
                    Y=torch.Tensor([train_accuracy]).unsqueeze(0).cpu(),
                    win=accuracy_window,
                    update='append')


Also, there is some good example here 28.