You’re right — if you just decrypt a section, modify it, and then re-encrypt it with the same key/nonce/counter values, you’ll be reusing the same keystream, which breaks the security of ChaCha20. A stream cipher must never encrypt two different plaintexts with the same keystream.
What you can do instead is take advantage of the fact that ChaCha20 (like CTR mode) is seekable. The keystream is generated in 64-byte blocks, and you can start from any block counter to encrypt or decrypt an arbitrary region of the file. That means you don’t need to reprocess the whole file, only the blocks that overlap with the data you want to change — as long as the key/nonce pair is unique for that file.
If you expect frequent in-place modifications, a common approach is to split the file into fixed-size chunks and encrypt each chunk separately with its own nonce. That way, when you change part of the file you only need to re-encrypt the affected chunks, and you don’t risk keystream reuse.
Also, don’t forget integrity: ChaCha20 on its own gives you confidentiality, but not tamper detection. In practice you’d want something like XChaCha20-Poly1305 per chunk to get both random access and authentication.