In functional programming, functions are not supposed to modify external state. All they are supposed to do is return a value based solely on their input. Their behaviour should not be affected by anything other than their input and the only effect they should have on the program’s state is the value they return. Which makes global variables useless, as a well behaved (pure) function cannot be affected by their contents nor change them.
And while this is an impure world, so the edges of any practical program need to find a way to model impure actions, the main body of code should remain pure (otherwise you lose the benefits of functional programming and might as well just use an imperative model and an imperative language).
So any state which should affect the output of a function has to be passed to it as an argument. In functional programming, state is passed from one function to the next. The output of one becomes the input of others.
Now, you could put all the possibly changeable state in one big hash/dictionary, but a) that would be cumbersome and b) it would make the program very sequential, with lots of unrelated bits of code becoming dependent on each other as they waited for their turn at the big ball of state. So well-designed functional programs only pass the relevant state along any particular thread. Which is similar to what well-behaved imperative programs do (having any one component only handle the relevant state).
In well-designed object-oriented programming, you build from objects a structure that will properly handle the state for which it is responsible. In functional programming, in a not entirely dissimilar way, you compose a structure from functions.
To make life easier for functional programmers, abstractions have evolved - applicatives, monads, arrows and others - which aid us in composing those structures. They help us orchestrate the transmission of state down a pipeline without making the smaller components tightly coupled to the larger structure. To put it more simply, they save us from having to add an extra parameter to each function so it can pass on the (hopefully not so big) ball of state owned by the pipeline
That’s how we do it. I hope it makes some sense to you. In my experience, though, functional programming is so little taught and discussed that that most people don’t understand what I’ve just explained until they try it for themselves.