Display Posts by Custom Taxonomy Chosen Terms

get_the_terms() returns an array of WP_Term objects on success, so you can’t simply pass the returned array to WP_Query, and if you want to query the related posts by the term slugs, then you can use wp_list_pluck() to get just the term slugs, although you can also use the function to get any properties of the term object like term_id:

$slugs = [];
if ( $terms && ! is_wp_error( $terms ) ) {
    $slugs = wp_list_pluck( $terms, 'slug' );
}

Then in your tax_query, use 'terms' => $slugs, in addition to setting the field to slug (see examples below).

See here for more info about the tax_query‘s parameters.

// Example 1: Query posts by term slugs.
'tax_query' => array( array(
    'taxonomy' => 'group',
    'field'    => 'slug', // if this is 'slug'
    'terms'    =>  $slugs // then this should be term slugs
) )

// Example 2: Query posts by term IDs.
'tax_query' => array( array(
    'taxonomy' => 'group',
    'field'    => 'term_id', // if this is 'term_id'
    'terms'    =>  $ids      // then this should be term IDs
    // assume $ids is wp_list_pluck( $terms, 'term_id' )
) )

Additional Notes

  1. the_title() already echoes the output, so no need to echo the the_title(). If you want to manually echo it, you could use get_the_title()echo get_the_title();.

  2. Secondly, a shortcode callback should always return the output. Otherwise, the output would be displayed at the wrong place — normally, before the post content is rendered. And if you need to echo something in a shortcode (callback), you would want to concatenate the output without any calls to echoing functions or for complex HTML, you can use output buffering — Stack Overflow has lots of info on that, but basically in your case, you could do:

    // At the start of the function:
    ob_start();
    
    // Then just run your loop...
    while( $loop->have_posts() ) {
        $loop->the_post();
        the_title();
        ...
    }
    wp_reset_postdata();
    
    // And at the end of the function:
    return ob_get_clean();
    
  3. If the query is not giving you the expected results after you confirmed all the query arguments are good, then you could debug the query by echoing the SQL command for that query — add echo $loop->request; after your new WP_Query() call, then see if the SQL is good and you can also copy the SQL and run it on phpMyAdmin (or a similar tool) and check if the SQL returns any results.

  4. If you want to exclude the current post, you can use the post__not_in parameter:

    new WP_Query( array(
        'post__not_in' => array( get_the_ID() ), // you need to pass an array
        ...
    ) )