All good answers here already - just be aware that your original loop with @choroba's correction will successfully make a very messy infinite string of processes spawned in quick succession.
Note that there are several useful variants. You could throw a delay inside the loop like this -
while true; do sleep 1 && date & done
But that won't cause any delay between processes spawned. Consider something more like this:
echo 0 > cond # false
delay=10 # secs
then
until (( $(<cond) )) do; sleep $delay && foo & done
or
while sleep $delay; do (( $(<cond) )) || foo & done
then make sure foo
sets cond to 1 when you want it to stop spawning.
But I'd try for a more controlled approach, like
until foo; do sleep $delay; done &
That runs foo
in the foreground OF a loop running in background, so to speak, and only tries again until foo
exits cleanly.
You get the idea.