Can I see specifically what React's diffing algorithm is detecting has changed? - reactjs

I'd like to gain visibility on the React shadow DOM diffing algorithm to debug a problem I'm having. Specifically, I'd like to see exactly what React will be changing on the next render. Only the className? The entire element?
tl;dr if you're curious, I have a css transition triggered by a class change which doesn't work, so I'm trying to figure out whether it's because React is seeing more changes than just the class and replacing the entire element (which I believe would prevent any style transitions from working).

Related

React & Canvas: changing state is breaking Canvas functions

I am trying to use a parent component to control animations in a child Canvas element. Specifically I want an animation to happen when a user inputs a correct answer.
It works until the user changes the state in the parent component, and then it no longer works.
I've made a stripped-back, minimal version of my code here to show my issue: https://codesandbox.io/s/epic-leaf-08jqvy?file=/src/App.js
My desired behaviour is that the red box bounces when a user clicks submit. That happens if they don't type anything in the input box, but as soon as you enter anything into there - changing state and re-rendering the component - the button no longer triggers the animation in the Canvas child component.
As far as I can tell, the issue is to do with changing the state when inputing text. If I make a version where the input is just assigned to a variable, it works fine, but I need to be able to use state and re-render other parts of it.
I have put a console.log in the jump() function, so I can see that it is being called, but no animation is taking place in the canvas.
I assume that what's happening is that everything is being re-rendered when the state changes, and so the useRef is no longer tracking to the right thing.
Things I've tried:
putting the canvas in a memoized component to prevent it from re-rendering
using eventlisteners to see if I can trigger the animations in other ways - keydown ones work, but I need the user to be able to type, so I tried other ones (like hashchange or audio.play) but neither of those worked.
You can see the thing I'm actually trying to build here: https://papaya-platypus-86565f.netlify.app/play Basically users answer questions and an animation plays depending on whether they're right or wrong, to give it a game-y feel.
Thanks!
I like your red box as well as your reasoning. Yes, the input state changing on keystroke is causing the entire App component to re-render. Note that your App.js component has a lot going on (all good stuff), such as your Box class instantiation, your canvas instantiation, etc.
The key is to break your components into smaller parts, particularly separating stateful components from non-stateful components. We don't want your canvas re-mounting on every input change, so we make them sibling components!
Here's a working example of your code, just in smaller components:
https://codesandbox.io/s/strange-julien-d3n4zm
I hope this helps.

vdom is finally updating the dom (after diffing) any dom change should actually trigger repaint & reflow of entire tree, then what is the use of vdom?

This question was asked manier times whenever we change a dom , like
Method 1 :
document.getElementByID('root')="hello"; even for changing one dom element , the browser rerenders the whole dom and state of the other elements like input text boxes will be lost, and recomputes styling and layouts (.ie reflows and repaints )
It is fine till now.
Method 2:
What react does is it keeps a virtual dom which is a copy of real dom, whenever a state changes, it rerenders entire new vdom in memory and does diffing and identifies which nodes to be updated in real-dom and react updates only that part in real-dom ,thus saving time not re-rendering entire dom.
My Question is at the end of the day either we update the realdom using method 1 or by using a vdom , finally dom is getting updated which in turn should make the browser compute the whole layout and styles again, why people say it helps to update only some part of the UI?
** Please kindly refrain from answering the same diffing concept, vdom concept, updating the required parts concept,or repaint and reflow process i.e dom tree css tree and rendering engine etc...**
# My question is how vdom can stop browser repainting and reflowing when ultimately dom is getting updated which in turn makes reflow and repaint whole tree?
picture about what I am trying to ask:
Ignore my grammar, and correct me where ever I am wrong at concepts of dom, vdom, repaint and reflow.
VDom will generally not save you any repaints/reflows compared to well-written DOM manipulation.
The main benefit of it is that it that it allows for a declarative component API. You describe what the component is, and React figures out how to render it efficiently without re-generating extraneous DOM elements. The html changes will generally be smaller using this approach.
Performance benefits here are somewhat of a red-herring. Yes, Reacts vdom has optimizations such as batching renders, but these are optimizations for the vdom, not for the browser. Browser DOM operations are already very fast.

React state issue (a bad setState?) when trying to show a component composed with styled components

Now I am not entirely sure what confluence of things brought this issue to a head, but lets start with my minimal reproduction
What am I trying to do
I want to show a styled element that is composed from various "inherited" members inside of a modal. Once the element is clicked, it will dismiss the modal.
Actual results
For some reason the element triggers it's onClick early, as soon as you click the button that is actually supposed to open the modal. It is only because it's a styled component (I think). If I change the element from a Para to a normal p, it behaves correctly.
I'm wondering, what can cause this? Is it that I nested too much? The error I get is
Warning: Cannot update a component (`App`) while rendering a different component (`Styled(Styled(styled.div))`). To locate the bad setState() call inside `Styled(Styled(styled.div))`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
The issue here is that you're spreading ...rest in your Para styled-component. Remove it from ./Para.js and it should work as expected

React - to manipulate DOM or use state?

This Is more of a "theoretical" question that often buffles me in different situations and use cases, I will give a simple example to demonstrate it.
Let's say I have a list of 10 buttons.
Everrytime I click a button, a floating menu appears on top of the clicked button - there is only one menu visible for any given time.
Let's assume that I can't render this floating menu within the button component and I can only render it in the buttons parent level (meaning that this menu is sibling to those buttons).
I have 2 possible options to do that:
Keep the x,y position of the last clicked button and render the menu in this given position
Render the menu once and using "ref" to directly relocate the menu
On the one hand, the first approach seems more "Reactish". On the other hand, the possible implemention I can think of is pretty ugly (capturing the clicked item position and saving it to state which triggers defender), and further more, I am not so sure about re re rendering the whole container just because I need to move a small piece of it.
The second approach touches the DOM directly using refs. Although possible , doing DOM manipulations sometimes feel bad to me.
Is there a better approach? Which of the 2 makes more sense?
Any suggestion or thoughts will be appreciated!
Thanks
React uses whats called a virtual DOM, which is a representation of the DOM, that sits on top of the real browser DOM. Whenever you update state or a user performs an action the virtual DOM compares and checks the changes with the real DOM and then updates the UI accordingly.
So if certain DOM elements like a are not different between changes it does not get re rendered, only the DOM elements that have changed are re rendered. And if a property on a DOM element is changed, only the property is updated and the DOM element is not re rendered.
<div color="blue" />
to
<div color="red" />
The whole element is not destroyed and re created, only the property is changed.
However if the element in the host tree is different than the entire host tree is destroyed and recreated.
<div />
to
<p>
This is refereed to as reconciliation
https://reactjs.org/docs/reconciliation.html
So using refs is definitely more of a hacky solution since its more of an escape hatch and directly manipulates the DOM.
I would definitely stick with option 1, I think there is an elegant solution to the use case you described, it would involve just adding a click event listener in the componentDidMount and keeping track of the click position that way.
And also its hard to say without code but since your buttons will be the same, they will not be re rendered only the menu will.
Would recommend for further reading
https://overreacted.io/react-as-a-ui-runtime/

What effect do multiple state components have on react app?

According to the docs, one should avoid having multiple components with state. I am in the situation where I want to make a text box that automatically expands vertically as the user writes, and for that I'm using this trick http://www.impressivewebs.com/textarea-auto-resize/, which means I need to get the height of a component. Now, I've been playing around with it a bit, and it doesn't seem feasible to pass a ref to my parent component which contains state, so the easy way out would be to keep a piece of state in the component with the textbox, and then use the ref from there.
This got me thinking, how exactly do multiple state components negatively affect my app? Is it only maintainability / comprehensability? Or are there actual performance issues with it? I've noticed a lot of open source react components that you would just plug in to your app keep state, meaning if you use open source components, chances are you will have several state components in your app.
It's totally ok to use local state for this kind of tricks on DOM. It's even better approach, than to share such implementation details to parent components.
In general, use this places for state:
Application-wide data in stores outside React (redux, flux-store, observables)
Form temporary data can be placed in store also. But if don't need it anywhere else except form, it's better to place this data in form component.
Tricks on DOM, short living and very local state can be placed in component that just need it
are there actual performance issues with it?
No. If you'll place all your state in components, your application will become even faster. Because when you update local state, only this component and it's childs updates.
But you shouldn't do that, because it kills maintainability.
lot of open source react components that you would just plug in to your app keep state
If component doesn't allow you to control it through the props - it's bad component. Usually open source components written to be easier to use, so they provide nice defaults, that allow you to just place component to your application, and be happy with that.
For example, Tabs component usually controlls selected tab using local state. But also it takes selectedTab and callback onSelect, so you can control it by yourself.
Stupid components (like your textarea component) should not have state with data. But they can have their own UI state.
In this case you can easily keep textarea height in state of stupid component.

Resources