Update. Instead of using filters (excerpt_more, the_content_more_link, or the_excerpt), I use preg_replace to render_block_core/post-excerpt. This replaces the text as expected. Hope this helps those who may have the same problem.
function custom_search_read_more_text( $block_content ) {
    if ( is_search() ) {
        global $post;
        if ( 'product' === get_post_type( $post ) ) {
            $block_content = preg_replace( '/(><a[^>]*>)Read more(<\/a>)/i', '$1' . 'View Product' . '$2', $block_content );
        }
    }
    return $block_content;
}
add_filter( 'render_block_core/post-excerpt', 'custom_search_read_more_text' );