I think you're making this too complicated. Instead of thinking every time you want to change an object, you just make a copy of that object with the properties changed. Some languages make this easier than others.
For example, in kotlin (java makes this more verbose) you can just say:
Code:
data class DataState(
val user: User,
val goldStars: Int,
val isOnline: Boolean
) {
fun setUser(user: User) = copy(user = user)
}
Then to make a new object of the DataState:
Code:
val newDataState = oldDataState.setUser(newUser)
in the above example, oldDataState is immutable and doesn't change. Anything referencing it always points to the same values. Immutability matters a lot more in multi-threaded applications (but thats most of them) because side effects won't occur as a result of the data changing