How to minimize the number of times I have to get data

Okay so i have this in a script:

game:GetService("RunService").Stepped:Connect(function()
	local returneddata = game.ReplicatedStorage.Game.Events.GetPlayersData:InvokeServer()

the data it returns is a table by the way.
I want a value to change to the table I want when that same table changes, so that I could use it in the script, and I don’t have to send an invoke every time.

Help and tips are always appreciated!

Make a remote event from the other end that sends updated data whenever it changes and store that in a table.

but how would i detect changes in a table?

You don’t need to. You send it on the other end and it will accept any changes.

no i mean the changes to the data in the server script (the data is a table too)

okay i figured out what i had to do, im gonna try it now

If you’re working with only non-replicated data (eg. tables) and not instances, you will have to make a method of communicating from server to the client regardless. However, instead of invoking the server to return the entire data table you can probably optimize and minimize the amount of data that needs to be sent by taking advantage of tables’ mutability and have the server send the directory of whatever is being changed to the client, and the updated value.

So if your data structure looks something like this:

local myData = {
    Settings = {
        SomeSetting = 'Some value';
        ShadowsEnabled = true;
    }
    Coins = 500;
}

And you want to update the ShadowsEnabled setting, you could probably update it on the client like so:

remote:FireClient('Settings.ShadowsEnabled', false)

Then to receive it on the client,

remote.OnClientEvent:Connect(function(directory, newValue)
    local currentDirectory = myData -- remember it's formatted as Settings.ShadowsEnabled, so we can split it by the "split" string which is a period
    directory = directory:split('.')
    for i, newDirectory in ipairs(directory) do -- newDirectory is a string
        if i == #directory then -- this is the final directory
            currentDirectory[newDirectory] = newValue -- this will set the value of myData.Settings.ShadowsEnabled to false as per the server's request.
        else -- this is not the final directory so we can continue to the next level:
            currentDirectory = currentDirectory[newDirectory] -- myData.Settings would be the value of currentDirectory (the settings table inside of myData)
        end
    end
end)

i dont really wanna change the value, i want it to be kinda more read than edit

Doing it like that would be behaviourally the same as reading it from the server, you’re just updating the table on the client instead of completely overwriting it which is less work for the garbage collector and less data will be sent (which is especially useful when working with a lot of data)

I have another problem, while i try to load the data and put that data into the value, the script just continues. but that is not good as some functions ask for data right away while the data is still loading.
how do i fix that?

If you constantly need to get data from the server, you’re probably better off replicating it and using a ModuleScript instead.

I’m not sure what you want to do here. Are you trying to make it so the client and server both share the same table? That’s not possible, and so you should only retrieve data from the server using RemoteFunctions when you need that data, rather than trying to constantly refresh it.

How would i do that? Would i have to change that value from the data serverscript to the module, and then require that in other scripts?