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.
Related
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.
I am trying to implement conditional rendering for our navbar's items depending on what page we're on (i.e. If we are on the chatrooms page, or "/rooms", then we don't want the "Chatrooms" nav item to render in the navbar). What I attempted to do was convert the Navbar into a class component, create a state for the currentPage and set it to window.location.pathname, and then created methods for setting the state and what nav items to render depending on the state, but it always requires me to reload the page when going from one page to another for the conditional logic to fully take effect. Is there a better way of achieving this functionality?
You could use react-router load content without refreshing the page. It's really simple to learn and use and you could probably get it up and running within an hour. You can Add Route components for the main content of the page.
When you route to a different page you could also call a setState function and change the currentPage, which in turn changes the navbar elements.
I've got an app that shows a list of items in a grid. Some of the items have an embedded video which flashes or stops playing (if it's already playing) when it's rerendered.
The list is maintained in Redux. When the user scrolls to the bottom of the page it loads more results which causes the Redux state to update which, in turn, causes the grid to rerender all of the items plus the new items.
I'm looking for a solution that will just add more items to the end of the grid instead of rerendering everything.
I've got a component that holds the entire grid. It renders a component for each item in the grid. In each item I have a component that holds the embedded video.
Any ideas?
If each item in the grid is a component, like you said, you should use React.memo (for functional compoents) or Reat.PureComponent (for class components). It will prevent the component from rerendering if the props have not changed. I can't guarantee your videos will keep playing, but if the only reason they stop playing or flash is because the component is being rerendered then it should fix the problem.
Maybe this can help: when passing information from redux to your component, try to update the list of the objects instead of sending a new one
It's redux UpdateObject method.
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 am currently using ant design tabs to control the tabs and within each tab I inserted a custom component within the TabPane. But the child custom component works quite unexpected. Before I clicked the tab title, the child component will not load (the constructor and componentDidMount will not be fired), BUT I want to load some data once the child component mounted to the tab instead of being shown.
Why it happened? ~~Ant Design~~ for performance concern?
Currently I am moving the data loading to the parent and handle them there. But still quite curious about the loading issue caused by ant design.