I am trying to debug performance issues in a React app,there is any method or 'devtools' or any means to check the performance of my component to prevent the failure of wasted renders
You can use https://github.com/welldone-software/why-did-you-render , its a more maintained up to date version of why-did-you-update (https://github.com/maicki/why-did-you-update) , it will print warnings in your console whenever an unnecessary re-render happens in one of your components.
Common optimisations you can do to prevent unnecessary renders include using PureComponent instead of Component, or use React.memo for function components, as well as hoist styles/object literals and function declarations outside of your render functions as they return a new reference every time.
You can check https://reactjs.org/docs/perf.html
Specifically take a look on printwasted https://reactjs.org/docs/perf.html#printwasted
“Wasted” time is spent on components that didn’t actually render
anything, e.g. the render stayed the same, so the DOM wasn’t touched
Related
Currently my project is still using mobx#4 and mobx-react#6 and I found this warning in the documentation:
Fair warning. Don't ever use React.useMemo to keep reference to the state object. It may be randomly thrown away by React and you may lose data.(mobx-react documentation)
I can't understand it, can anyone help with an example and the reason why?
Quote from React docs:
You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance.
Basically React can reinstantiate memoized value at any time if it wants to and you will lose your whole Store because it will be recreated with default parameters.
It might not do it right now, but it is better not use memo for persistent values so you won't be forced to make refactoring if you migrate to future versions of React.
Link: https://reactjs.org/docs/hooks-reference.html#usememo
I've placed debuggers in the render of a component and see that it gets ran twice sometimes, if not most of the time. Is it because the first render is before the component receives any props? And the 2nd time is when it receives it? I thought components go through the lifestyle of mounting, receiving props, and then rendering? Or does it mount, render, check props, and then re-render?
Components do not re-render if they have initial props. The only reason that it would re-render is if it is receiving props after the initial render, or if you are changing state.
In my previous question, I had an issue, and I quote:
" ...I know that most of these features (and possibly more) are available in function components (introduced most by hooks), but they do not work as I intend them too, because they are NOT exactly the same, like useEffect(() => {code}, []) is known to replace componentDidMount(), an yet upon mount it renders twice in any app I develop, passing false data... "
To that issue, CertainPerformance replied:
" ...Sounds like you have strict mode enabled and are performing operations with side-effects, which should be avoided. You probably just need to figure out the right way to structure the code with functional components - nearly anything you'd want to do can be done reasonably elegantly in functional components, though not absolutely everything... "
Which lead me to research a little and find this interesting answer:
It's an intentional feature of the StrictMode. This only happens in development, and helps find accidental side effects put into the render phase. We only do this for components with Hooks because those are more likely to accidentally have side effects in the wrong place.
You can read more about that on GitHub.
I'm having a huge form built with react and material-ui. The form uses two way binding and update state for input changes. changing any input filed cause all components to update (obvious by react developer tools TraceReactUpdate enabled). When it comes to TextField it makes my page rendering very slow. using this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this) doesn't help.
It can be extremely difficult to find issues like the above, because it totally depends on the actual code you have written. I am sure that the react rendering concept works (as it has for myself and so many others), but without seeing more code it is impossible to pinpoint the actual problem.
Still, I have a feeling that the real cause is "simple", meaning that it is very likely due to a prop being passed that has indeed changed. Maybe not in value, but in instance. IIRC, the PurerenderMixin is not comparing values (unless the data are value types), it is comparing instances. So even if the data is the same, if the instance has changed then it will re-render.
Some key-points to consider:
Are you passing just the props that you need to each component, or are you passing all props to them all?
Are the data-structures immutable?
Are you sure that you are not passing data that changes on the iterations, like passing the javascript [] as a prop will mean that the data has changed (see https://medium.com/#esamatti/react-js-pure-render-performance-anti-pattern-fb88c101332f#.hx97qk4tx for sample on how this can screw up your day).
If you explicitly create a shouldComponentUpdate() method for the components then you can control this yourself. The PureRenderMixin does a shallow check to see if the props have changed, but, if you are passing them all then no matter if they have been used or not in the render method then just one of them changing will mean that the component is considered to need to render (as in, not mount, but render in memory and reconcile possible changes with the dom). Using shouldComponentUpdate can help stop rendering based on your own checks.
Using immutable props can also be helpful. The React PureRenderMixin only does a shallow comparison, as mentioned. So, if you are passing data-structures in the props that have depth (like sub-properties), then these are not checked. Meaning that you could end up with the opposite problem you have now, that is components that should have updated but aren't. If you are using i.e. redux and have done "the right thing" and are using i.e. Immutable.js, then using the PureRenderMixin is good enough.
Reading the specific docs for this may or may not help. There's some good description of this in the React manuals: https://facebook.github.io/react/docs/advanced-performance.html#shouldcomponentupdate-in-action
And - I forgot to say, if you are using redux then you could consider these somewhat elegant and simple ways of handling your forms:
http://redux-form.com/
https://davidkpiano.github.io/react-redux-form/
Hope that this helps. Good luck.
I saw this line as an answer to another question on here:
"componentWillMount should be componentDidMount, or else you'll leak event emitters in node."
and I don't really understand it. Can someone explain with more detail?
More info:
Building a react application with flux, as part of the initial render, a child component computes some data. Ideally, after this data is computed, I would like to call an action that updates the store's state with a portion of this new data.
Normally, updating the store's state emits a change event that causes a re-render. However, because the change listener isn't being added until componentDidMount (rather than in componentWillMount), my top level component isn't able to listen for the change that occurs during the initial render and initiate a re-render.
If I move the addChangeListener to componentWillMount that would seem to fix this issue, but the above quote suggests that this is a bad idea?
I think the prevailing wisdom that listeners should be set in componentDidMount because it prevents problems in isomorphic applications is a mistake. I think in 98% of cases for non-isomorphic applications setting listeners in either componentWillMount and componentDidMount will work the same way, but it is conceptually wrong and in the 2% of cases (such as the example given in the original question) it will do the wrong thing.
There are git issue discussions and comments in the React source code suggesting that it would be preferred that componentWillMount wasn't called on the server at all, but if it isn't then problems are created in the checksum test comparing the server prerender to the client initial render. Having componentWillMount on the server means that it isn't executed as part of the component lifecycle in this case, but this is being used as an excuse to not count it as part of the lifecycle in any case.
In fact, componentWillMount is exactly the right place to register listeners if you are not creating an isomorphic application. If you are creating an isomorphic application then you have to make some compromises due to the checksum/lifecycle issue not being ideal in this case (maybe just testing for the server environment and then not registering listeners?).
In non-isomorphic applications adding listeners in componentWillMount can save unnecessary re-renders in some cases and will register them in document order. The advantage of document order is that if you have a way to flush pending events as components are re-rendered (for example, takeRecords on a MutationObserver) then you can ensure the document is re-rendered top down instead of bottom up, converting the rendering complexity to linear from polynomial.
Additionally, there is no danger period between the initial render and when the listener is registered where the Store can change without triggering a render, causing the view to be out of sync with the Store (the example problem given in the original question). If the listener is registered in componentDidMount you either need to make sure the Store isn't changed in componentDidMount calls in children, or else force a re-render/re-sync after registering the listener, which if done in componentDidMount is done in reverse document order which may be polynomial complexity (depending on how/if the React setStates are aggregated).
Is hard to understand what that quote means without more context. What I can tell you is that there are huge differences between the two of those methods.
On one hand, componentWillMount is called before the component is actually added to the DOM. This is the last chance you have to update component's state and get it rendered before the component is rendered by the browser.
On the other hand, componentDidMount is called once the component has been attached to the DOM (the real one).
What you need really depends on your use case. In general, componentDidMount is used to integrate with other libraries (like jQuery), it provides a way to modify the HTML rendered by the component.
I suggest you to read these links:
https://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount
https://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount
https://facebook.github.io/react/tips/use-react-with-other-libraries.html
So I am looking to write integration level tests (where you are talking to a real database and really nothing is mocked) for a ReactJS application and figured Selenium is the default choice for this type of testing. With Angular 1.x, you can tell if angular's digest cycle is still process the DOM which removes the need to add in sleeps which are inefficient and flakey.
Is there something similar in ReactJS that I can use instead of a bunch of flakey sleep commands?
Always rendering from a root component
There's a callback that you can pass to the render function:
ReactComponent render(
ReactElement element,
DOMElement container,
[function callback]
)
You can also listen to the componentDidUpdate method of that top component.
Unfortunately this will only work if you always render from the top component, which somehow means you manage all the state outside of React, without using any local state, and use it in a purely functional way as an efficient templating engine. Some frameworks help you do so.
Even Flux does not really enforce this (at least the original implementation) because Flux stores are not necessarily injected as props from the very top. (They are in atom-react)
Not always rendering from a root component
I don't know there is any elegant solution to this problem but here's what I would do:
Implement all lifecycle methods on all your components, for example with a Mixin, and call a global function notifyReactIsWorking from these callbacks
Debounce the notifyReactIsWorking with _.debounce(changeMeter, 1000, false)
This way, when notifyReactIsWorking gets called, this somehow means that React has stabilized because not a single lifecycle method has been called for more than 1 second.
This is a hack but probably should work in most cases.
Also interested in more efficient solutions :)