Serial Input Basics

To add to Robin2's good comments, the classic blocking serial function is the readStringUntil() function you mention: it's convenient and powerful, but until the specified character is received, the sketch will block and do absolutely nothing else. Some simple sketches can tolerate this, like the ones that illustrate using that function, but most embedded systems must still go on doing the things they do while waiting for serial input. Therefore, the non-blocking techniques that Robin demonstrates are needed.

As for the String class, the issue is that it frequently allocates and frees chunks of dynamic memory as string contents change. Do a search on the terms heap fragmentation and memory leak to see why this could be a problem in the very limited RAM that is typically available to sketches. The string functions that Robin2 mentions work on fixed character arrays, and while they may not be as glamorous, they do not have these memory issues (but you do need to be careful about overrunning your buffer and trying to stuff too much into it.)