In general, you should know what you have previously sent to the client, and you can base the next update based on that.
If you're using a lossy channel, then you can instead know what the client has last acknowledged, and send updates based on that. This needs you to number packets and keep some maximal acknowledgement window, and each packet needs to include a signal of what the last acknowledged packet seen was.
Another alternative is to just send inputs, and use deterministic (-ish) simulation/physics, and only send occasional baseline/checkpoint updates – say, once every 5 seconds or so. Plus send corrections when non-predictable events happen on the server, such as server-side collisions between players.
However, this is a huge space of design possibilities, and which method is “best” depends a lot on what the specifics of your game are. A twitch shooter with line-trace weapons and limited number of players per level, like Counter-Strike, is very different from a social RPG MMO with a largely fixed terrain like World of Warcraft, is very different from a racing/driving simulation like Forza, is very different from a virtual world with user construction like Roblox. Targeting mobile phones or worldwide play is very different from targeting local LAN and geographically near hosted servers. You need to make it clear what your gameplay demands, and why, and then design your physics/simulation, rendering, and networking, to cooperate to generate the experience you desire.