Basically every call of a functional component MyComponent() represents a new scope. When you're working with a hook such as useEffect(), you have to pay attention to the dynamic scope so and correctly trigger the useEffect() with the dependency array.
Correct, but the callback passed to useEffect is only scoped to the call stack triggered by the dependency array. So, this makes the callback passed to useEffect dynamically scoped.
The callback is always defined it's just not always invoked. Otherwise it's a regular lexical closure like any callback in JavaScript. Maybe I'm not understanding what you mean by dynamic scope.