The two families are constantly swapped because both “clean up a string”. Sanitising decides what is allowed to be stored; escaping decides how it is rendered safely in a particular context. Doing only one of them leaves a hole.
// input: strip what should never be stored
$title = sanitize_text_field( $_POST['title'] );
// output: encode for the context it lands in
echo esc_html( $title ); // element text
echo esc_attr( $title ); // attribute value
echo esc_url( $link ); // href / src
echo wp_kses_post( $body ); // allowed markup only
Escaping is context-dependent, which is why there is more than one function: a value that is safe inside a paragraph can break out of an unquoted attribute. Escape at the point of output rather than on the way in, because the same stored value may be printed into HTML, an attribute and a JSON blob on the same page.