Trying to write React applications in an imperative manner (the more traditional approach to programming as opposed to declarative), twisted my head in knots and made things harder and more complex than they needed to be.
What I mean by writing React applications in a declarative manner is:
1: you have a global state in your application
2: the global state includes an object with information about what state the application is in, for example:
globalState = {
"DisplayingFormEditUserProfile": false,
"DisplayingFormViewUserProfile": true,
"DisplayingSideMenu": false,
"DisplayingTopBanner": true,
"DisplayingUserSignedInStatus": true,
etc etc
}
3: use React context to manage this state.4: components decide to display themselves by querying the global state
It becomes easy then for your buttons and links to simply adjust the global state to make things happen. Because React rerenders the application each time the global state changes, you need do nothing explicit (imperative) to drive the application - it all just happens automatically as a result of what actions the user takes - actions that alter the global state.
React hooks and context make this approach very easy and clean to implement/
That's the way I do it anyway - an approach I find makes the entire application easier to understand.