Dropdown menu on custom page with product to choose number of products per page

Maybe this would work?

function ps_pre_get_products_query( $query ) {
    $per_page = filter_input(INPUT_GET, 'perpage', FILTER_SANITIZE_NUMBER_INT);

    if ( ! is_admin() && is_woocommerce() && is_page() ) {
      $query->set( 'posts_per_page', $per_page );
    }
}

I tested your code and the if statement didn’t seem to work with is_page() (but that could also be because my local WP sandbox is a mess). To my knowing posts_per_page expects int and var_dump showed that $per_page was a string.

EDIT My local WP sandbox is a mess, so that’s why is_page wasn’t working. I tested the code again on another install.

EDIT 2 Let’s see how many times I can get this wrong. I updated the code to something that works (at least on another local WP sandbox).