Update AppBar Title with only re-rending the AppBar - reactjs

Objective
My goal is to have an AppBar at the top of the page that has a title in it. Then in the "Main" area of my screen I will have a route that renders a different component depending on the url. These are the components that need to update the page title that is being rendered in the AppBar. I only want the AppBar to re-render and nothing else, because it's the only thing that will have actual data change in.
Originally I was using useState() and just prop drilling the [pageTitle, setPageTitle] down to the components. From what I've read, you should avoid prop drilling if possible.
So I've tried leveraging useContext() but everything in the tree still re-renders.
Caveats
I would like to keep the layout of the HTML like I currently have it if possible. I'm not sure if that affects anything.
How I Tested For Re-rendering
I have console.log() statements per component. I got rid of strict mode in order to make sure the components are rendering only once. I tested this prior to leveraging useContext and the statements only print out once.
Now when I click on a navigation link you will notice it prints out a console.log() for all of the components that <PageTitleContext.Provider> is wrapping.
I only want the <AppBar> to re-render and nothing else, because this is the only component that is displaying the pageTitle.
Sandbox Code
https://codesandbox.io/s/appbar-page-title-update-m5y9el?file=/src/pages/Dashboard.jsx

Related

Component using "Suspense" showing spinner on consequent loads (changing its height for a moment)

I'm rendering a number of items, where each individual item uses the same component:
This component internally uses Suspense:
<Suspense fallback={<Spinner />}>{children}</Suspense>
Whenever I click the paginator, a new set of items is rendered. Each of the items uses the same "Suspensed" component.
Problem: Each of the instances shows a fallback (spinner, loader) for a moment, and only then its content.
Since the fallback has constant height, this changes the height of the parent container, which makes the whole page jumping around:
I'm wondering how could I fix this? Basically, I'd like to avoid the new set of items to collapse due to showing the fallback. Sure, showing the fallback on initial load is fine, but I don't think the already loaded component (dynamically imported code) should show it on consequent pages.
I tried using React.startTransition, but that didn't help.
I also checked with components which are not lazily loaded, and everything works fine (parent height remains constant).
Thanks for help!
Update: I came up with a "poor man's fix":
wrapping children inside 2 divs
ResizeObserver monitoring the height of the inner div and setting the same height to the outer one, but in debounced fashion (100ms later)
Resources:
https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver
https://www.npmjs.com/package/use-debounce
Note: You'll probably need to mock ResizeObserver in your Jest tests: https://github.com/que-etc/resize-observer-polyfill/issues/50#issuecomment-488064120

Framer Motion animation repeats on state change

I am building a task manager with React and Framer Motion. I'm animating a slide in transition for a react Portal / modal. The portal has a form in it with multiple input text fields in it, each with their own onChange handlers. However, whenever the onChange handler is called, the animation replays itself. I'm not sure what is the issue.
I've tried to add a repeat value of 0 to the transitions, but there seems to be no change. I'm pretty new to framer motion, so please let me what other details I need to provide.
If you are using animate prop, the component will animate on each render, this is useful only for simple cases, where the component typically renders once on the page. But in your case, this prop will not work since the input field re-renders on each change.
For your use case, it's better to use useAnimation() hook and pass the animationControl as variant prop and fire it manually on the first render only.
useEffect(() => {
if (firstRender) {
animationControl.start();
}
}, [])

React - rerender after content becomes visible

I have a React (hooks) component inside an Accordion (<details> element).
The component makes some assumptions about offsetWidth for some child elements being available, but as the accordion is closed, the component is not visible and these Refs have an offsetWidth of 0.
I need to re-render the component, after the accordion is open and the component itself becomes visible.
I am trying passing the state of the accordion (open/closed) down to the component to trigger a render when this changes, but useEffect is run before the browser draws the component, so width is still 0 even if accordion state is open.
Any idea how to solve this?
Well actually useEffect is called after the component re-render. So that is probably not your problem.
I suggest using the state for dynamically adding a class with display: none and removing it. instead of changing its width to zero

React Transition Group: What is the purpose of TransitionGroup?

I'm looking to use the React Transition Group library to animate some stuff in my React page. According to those docs, the TransitionGroup component does the following:
The <TransitionGroup> component manages a set of transition components
( and <CSSTransition>) in a list. Like with the transition
components, <TransitionGroup> is a state machine for managing the
mounting and unmounting of components over time.
Consider the example below. As items are removed or added to the
TodoList the in prop is toggled automatically by the
<TransitionGroup>.
I'm not really sure what that means or why it's important.
Also, when I modify the example code that they embed on the documentation page so that the <TransitionGroup> tags are replaced with <ul> tags everything seems to work just fine (I can remove todo items by clicking on them, I can add new todo items).
Why is <TransitionGroup> component necessary? What does it do? (And why do things appear to work just fine when I replace it with an unordered list?)
React Transition Group has some advantages over typical css animations.These are some points that are coming to my mind.
Its uses binding to change classes for a components. eg: enter, appear, enter-active, appear-active, exit, exit-active etc are all part of animation classes. This make it really interactive interms of rich animations which you can not achive otherwise.
It has advatage to unmount your component using javascript, once animation is done. So basically no extra load on your front end.
It gives your freedom to define animations which ever way you like. Either css classes or defineing your own styles with in js file.
It gives you various type of animation options. Eg: Switch Transitions, Transition Groups, CssTransitions etc.
I would suggest to keep experimenting with typical css animations and react transition group and come to your own conclusion.

Rendering specific divs in React

I have a top div (a) and two bottom divs (B, C).
When the top div is updated I want it to only cause rendering in div C and not in div B
how can I do that?
It all depends on how you manage your application state. If you have local state of props in C that change in response to some action in div A then React will detect that and rerender the modified components.
It's not good practice to force React to re-render certain components. Just change your state and let React do the rest.
You can use shouldComponentUpdate() method in your B component.

Resources