When developing say a new widget (or heavily extending an existing one), you can develop basic functionality, commit, add bells and whistles, commit, and some more stuff, commit, send for code review, do the fixes, commit, ask for re-review maybe, and then squash the commits into one commit if needed. With DVCSes like Git it's extremely easy, and reviewing smaller commits is easier than having to go through a behemoth (of course it always depends on your particular situation).
I sometimes tend to open half-baked pull requests to ask for quick early feedback if I'm doing things the right way, and what to be careful about, and continue developing in background while the more senior person takes a look at the code.
You can make all those changes in distinct, clean commits, but if the reviewer works commit by commit, they have to follow the evolution of your code rather than simply review the final state. You might argue that provides a basis for a better review, but it's also much more time consuming for the reviewer.
You can of course split a huge commit into smaller ones using sth like `git add -p` but it's way more work than just doing lots of small commits regularly and then squashing them into medium-sized commits before the review. I like to do temporary commits regularly as "checkpoints", meaning, "this code works", and anytime I make a stupid mistake and break something, I can analyze a short diff to find the bug I just introduced rather than trying to figure out the bug just by looking at the code. It's usually a lot faster for me.
If you're really unsure of the design, then tackle that in a design doc first. Discuss what the API will look like, write out sample call sites to show its use. Otherwise, yeah, you'll probably end up re-writing it.
Small commits have another benefit: they can be moved (cherry picked, for example to backport) or reverted easily.
I think it's easier to look at two different versions of checkins, than to hoard code and make a single huge checkin.