Closed FezVrasta closed 4 years ago
I also noticed the axe audit can take up to 2 seconds to complete a cycle, is it expected? I understand this tool is only for local development so my users will not be affected, but it really makes difficult to test the application while I develop.
Seeing the same thing, even if I change the debounce timeout to something very large, like @FezVrasta explained.
We're considering disabling react-axe now, which I don't want to be the solution, but I'm worried we will miss actual performance issues if this continues to cause lag. 😕
I'm experiencing overall slowness of my app as well, and am considering disabling axe as well for the same reasons as @atdrago :/
We currently hook into componentDidUpdate
. So, when typing in an input that doesn't use a guard against updating state, componentDidUpdate
will fire even though (usually) no changes were made to the DOM.
Try using a guard like:
getSnapshotBeforeUpdate
if
-check in the onInput
handlerThis way, setState
or hooks will only trigger componentDidUpdate
when the input change will affect the render (examples):
Exactly what triggers a render will depend on how granular/composed your component is and which props are passed through from an onInput
update.
While this doesn't fix the issue with the debounce parameter, hopefully it will fix your problem during testing until we can hook into a different part of the lifecycle--something closer to the real DOM changes.
I need to listen to onChange
and update on each keystroke (because I'm using that text to generate somethin else in real time).
I would expect the debounce option of react-axe to exactly avoid this kind of situations.
@FezVrasta when you "generate something else" do you need that echoed to the DOM?
Also, I agree about the debounce option I'm just offering a temporary solution until that gets a fix. YMMV.
@AutoSponge yes, it's echoed in the DOM, but throttled. So basically the loop between input[value]
and its state is instant, but then the derived rendering is throttled to avoid continuous rerenders.
@FezVrasta that's where I think you could use a snapshot if you're not already to avoid triggering a component update (updates don't always mean renders but they do always mean react-axe will fire):
/*
* onInput => handler fires that calls setState after a 200-300ms delay (avg. typer)
* but always uses the latest value of the element instead of what initially
* triggered the event
*/
getSnapshotBeforeUpdate(prevProps, prevState) {
if (/* we really want to render */) {
return (
this.state.inputValue
);
}
// we can wait for another event, like when the user no longer focuses the input
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (snapshot !== null) {
// do the thing with the value like update store or context
}
}
Thanks for the tip, unfortunately the one I reported is just one of the cases where I get this problem, but I'll keep this in mind as a possible optimization.
I don't mean to pile on, but I just want to add this in case it helps.
I'm seeing the same lag for checkboxes as well, not just text input fields (i.e., click, wait ~200ms, checkbox becomes checked). If I comment out the react-axe initialization, the delay is gone. Unfortunately I don't think the snapshot workaround above would help here, unless I'm misunderstanding.
Thank you for looking into this! It's very much appreciated!
@atdrago thanks for joining. It's not piling on. It's just more evidence we need to consider using something like MutationObserver instead of the React life cycle since React doesn't emit DOM changes.
For any native input, you can still tell React not to update. It doesn't need to re-render to display the changes. Only if you manipulate the input (like autocorrect or auto-formatting functionality). Also, the size of the tree being evaluated by axe is based on the component that changed. If the "CheckBox" component changed, only that tree is evaluated. But if you use a native checkbox in a very large "Page" component, the entire page will be checked.
Again, it's not a fix for this issue, but maybe you can get some temporary relief without disabling the tool.
@AutoSponge I appreciate the response! Our project is using functional components and hooks, and we haven't had any reason to convert them to class components, which is what we'd need to do in order to use getSnapshotBeforeUpdate
(there's currently no available hook for that). Unfortunately this isn't a great solution for us.
I was reading through the code and I think it helped me understand the problem. Since we need to hook into componentDidUpdate
, we need to run checkNode
on every update, on every component that gets added.
I think I might be oversimplifying the problem, but could debouncing help as a quick fix? I was messing around, and in index.js
I debounced the checkNode
function that was passed into the componentDidMount
and componentDidUpdate
handlers. I saw a large performance boost after this and the lag was gone. My only concern is that, since checkNode
is called against several different nodes, if it is debounced then I think the axe checker would only get run against the last node it was called with. I was still seeing axe errors in the console though, so maybe I'm wrong?
There's a related ticket, with a proposed solution for this in axe-core. I think react-axe can probably throttle, but I'd prefer axe-core to be able to handle this. https://github.com/dequelabs/axe-core/issues/1867
Sorry to jump in here. Happy to make another issue if thats preferred.
Sadly, we're also seeing this issue and will likely disable react-axe until it is viable for development of our application. I'd love to see a solution that uses something like MutationObserver instead of the React lifecycle. That seems more aligned with what axe is aiming to help solve (invalid DOM).
I've found react-axe@3.3.0 to be unusably laggy. But downgrading to react-axe@3.2.0 with axe-core@3.4.1 works fine.
react-axe 3.4.1 was just released which should fix the performance problems by respecting the debounce timer parameter. Please let us know if you are still experiencing problems after upgrading.
Unable to execute react-axe, because of an update of chrome. Making the tiket work in progress and will verify once issue fixed.
@straker , Please make a file with an input field in the react-axe container (/components)to test this ticket
Any updates here? My team is also experiencing a lot of lag on version 3.5.3.
@savybrandt are you experience lag even with the debounce parameter? If so, I'd like to investigate that further. Could you provide more details, perhaps in a new ticket?
Closing as the issue seems to have been resolved.
We have moved this package to be under our axe-core-npm monorepo for easier management. As a result, this repository will be deprecated in the coming weeks.
If this is still a problem, please feel free to reopen in the new repository.
Hi, I got an input field that updates some local state (
useState
).When I type in the input, I see a lot of react-axe calls being performed even if I defined the 3rd argument to be
1000
(I even tried 10 seconds).The calls you see in the screenshot are 213ms and are called one after the other, so from what I see the debounce option is not working as expected? (or at least how I would expect).
This is how I initialize axe:
Do you have any suggestion?