I have a component that is a navigation bar. The navigation bar persists within all screens in specific parts of my project, and is the highest level component at all given times.
Is it possible to somehow get a page-change event (so if I go from say, /main/viewer to /main/documents ) without having a callback triggering a pagechange going from navigation bar all the way down to the viewer component?
These components are nested in each other, as the NavBar displays main screen, which then directs to different component for different screens, which in turn have components that call different screens based on buttons pressed, etc etc.
I'm trying to get the simplest way to get a page-change event, so that I can trigger a function in viewer, which prompts to save any edits done, if page is about to be changed through the nav-bar (or another means) and not via a button in the viewer.
currently, I navigate between pages/components by using this.,props.history and then either .push("path", props) and .goBack() which is usually the last line on a function to handle exiting the component.
Related
I'm trying to implement a page transition animation that works as follows:
User clicks a link on the website
A block slides down from top to the bottom so the whole screen turns into the block's color
After a short delay, the block disappears by sliding down further
User sees a new page opened.
The libraries I use are:
React
React Router Dom
Transition Group
GSAP
You can find the current implementation here: https://codesandbox.io/s/frosty-brook-3dl6y5
The problem is that the animation gets triggered after the new page is opened (i.e. user clicks a link, sees a new page's content, and then the animation starts).
I've already tried many different things, including replacing onEnter with onExist in PageTransition component, however, nothing worked.
How can I update my code so the animation gets triggered before the new page loads?
Just in case, I'm ready to switch to any open source library that would allow me to achieve what I described above.
In my React app, I have tabs at the top of the app, a sidebar for navigation and a section to the right of the sidebar, and below the tabs that show content. When the user clicks on a tab, the sidebar loads its navigation data from the backend. Then after loading it, by default it selects the first item in the sidebar and loads the content details. The content details are made up of different components and several backend calls may need to be made.
What I would like to do is display a progress bar just above the tabs which is shown the moment the user clicks on the tab. The progress bar is only dismissed after the entire content for both the sidebar and content details has been loaded. The sidebar and content details do not update or are even shown until they have completely retrieved all their data from the backend and done any other initialization.
Determining exactly when all the content has been loaded is tricky as each component in the sidebar and content details are responsible for retrieving data from the backend. The only solution I could think of is for each component to implement a publisher/subscriber mechanism. Each parent component notifies each child component that it needs to load its data. When the child component receives this notification and has retrieved its data from the backend and finished any other initialization, it then notifies the parent that it has completed. Only when the top-level component gets all notifications from all its direct children, does it then dismiss the progress bar and cause the content to be displayed.
Another possible approach is to have only the first child component retrieve all the data from the backend on behalf of all the descendent components and cache it in the local repository. This would eliminate the need for descendent components from having to call the backend and could quickly just retrieve the data from the local repository. But there is still the issue of initializing each nested component. If I show the entire content while it is still in the initialization phase, the user would notice this. Still, I suspect React renders most stuff so fast that users will probably not notice it.
I'm not sure if this is the approach I should be taking or if there is something more inherent in React that handles this.
A similar website where you can see this is at Google's:
https://fuchsia.dev
although this site probably has much fewer backend calls than the one I am working on. But in general, this is close to what I am looking to achieve.
Your solution with the subscriber pattern will work fine, but if you want something less complex, there are two common approaches:
If you are using redux, every child component dispatches that it is loading data right now with their unique id. When it finishes (or component is unmounted), it dispatches an action to remove the loading information. Parent component just checks redux store, if there is anything loading.
The second approach without redux is to pass a callback to the child components from the parent through props. This callback expects two parameters: unique id and bool value representing if the child components starts/finishes loading. When the child component starts loading, it calls the callback from the parent with a unique id and value true. When the child component finishes loading, it calls the callback again with the same unique id and value false. Parent component set to its state which child components are loading and renders the loading accordingly.
I used react-infinite-scroll-component it's working just fine.
However, I want to avoid making the user lose his scroll position when he leaves the page and clicks back?
Also please put on consideration Firefox and Safari.
Not 100% sure because I haven't used it - but since no one else has chimed in... the docs say the component has a prop named key that is described as:
the key for the current data set being shown, used when the same
component can show different data sets at different times,
default=undefined
Also, it has a prop named onScroll that is described as:
a function that will listen to the scroll event on the scrolling
container. Note that the scroll event is throttled, so you may not
receive as many events as you would expect.
... which I suspect one of the arguments of which will tell you which keys it loaded / scrolled through.
So my approach would be to use componentWillUnmount to save the last key it loaded into a parent property (or Redux store if you're using Redux)... and when the component loads, if the key exists in the parent (or Redux store if you're using Redux) then pass it that key.
My page is composed of hierarchy of classes and many reusable components. Multiple instances of a button component can exist anywhere in the page and on click they fire actions that populate different types of data in a common sidebar list component.
The requirement is to highlight the button that was last clicked to load the data in that sidebar list. Of course, it also means to remove highlighting from the previous button. Since these button can exist in different components, I cannot manage state in one parent component.
I am not able to find a solution in pure React. I don't want to use jQuery rather just stick to React. Note I do use Redux in the app though and would be fine with leveraging Redux state if required.
You should most definitely use Redux. You'll need to create a variable in Redux that gets updated whenever an action takes place that would require you to highlight the button on the page. Then use conditional styling for the button based on that variable.
I have four buttons and each button displays different information such as text, photos, map etc. I want to press a button and display information below it without navigating to a new screen.
Make each button set the component state, and have your render method query that state. Based on what the state is, you render method can display different components.