-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error: Maximum update depth exceeded #12
Comments
I have the same issue. And also I see <TruncateMarkup lines={3}>
<span>
<Linkify properties={{ target: '_blank' }}>{message}</Linkify>
</span>
</TruncateMarkup> |
I've reproduced it in this codesandbox. |
Thanks for the report (and codesandbox ), I'll take a look. @jflayhart any chance you can provide a repro case (codesandbox) too? Just to help verify the fix |
Update - I found the issue and it's not a small one. It affects HOC/render prop components (that's the case for @modestfake's example, as the |
@patrik-piskay no rush, thanks for your time, appreciate it! |
So here is what I found out... Issue: Solution: tl;dr: there is none that I am aware of that works for every case, so in dev mode we'll warn if React components are used as I've spent a few hours trying to get React components (both classes and functions) to work. The reason it's not trivial is because of the way the truncate functionality works here. General approach is to take the whole element tree structure ( <TruncateMarkup>
<div>
Hello <span>world{'!'}</span>
</div>
</TruncateMarkup> ↓↓↓ { type: 'div', props: { children: [ 'Hello', { type: 'span', props: { children: [ 'world', '!' ] } } ] } } which is easy to work with as we have the whole final "render" tree available, which means we can potentially end up with this result (after truncation): <div>
Hello <span>wo</span>...
</div> But if we were to move a part of the tree to a separate component, it could look like this: const Person = ({ person }) => (
<span>{person || 'world'} </span>
);
<TruncateMarkup>
<div>
Hello <Person />!
</div>
</TruncateMarkup> ↓↓↓ { type: 'div', props: { children: [ 'Hello', { type: 'function Person()', props: {} }, '!' ] } } which hides what's getting rendered in One idea I had to solve this was to "unwrap" the whole tree before starting any truncation work by "evaluating" these nested components: if (typeof node.type === 'function') {
if (// class component) {
const instance = new node.type(node.props);
return instance.render();
} else {
// function component
return node.type(node.props);
}
} This actually worked and I was able to get nested components to work, until...it didn't. Some components I used for testing used context, which this approach didn't support. Even before trying this approach I felt it's probably not the best idea to start emulating React itself by rendering the tree on our own, and when I experienced the context issues, I decided it's (probably) nothing we can solve reliably, so the best thing we could do is to officially not support it - we'll warn if React components are detected in the
<TruncateMarkup>
<div>
Hello <span>world{'!'}</span>
</div>
</TruncateMarkup> |
Thank you @patrik-piskay for the detailed explanation! Really appreciate your effort and time! Maybe you've already thought about this, so I just wondering, can you use refs? With refs you can have a full access to the DOM, rendered by React. (I'm not sure I understand how your component works, so I might be wrong, don't blame me for that 😕 ). |
The issue with refs is that it returns actual DOM nodes instead of React elements. So instead of
we get
That means we'd need to transform the returned DOM nodes back into React elements again (or any tree structure so we can truncate it and have it rendered again), which might be doable, but again not reliable. For example, I don't think events (click etc.) would work. Also, we'd lose access to any React components after the initial render (because we'd continue working with the initially returned DOM elements), so any effects happening in their lifecycle methods would be lost. It's probably best to keep it simple for now and use DOM elements only. For the future, who knows, maybe with Hooks there will be something we can do to support React components, I'll keep my eyes on it. |
Got it! Thanks again! |
I just published a new (major) version that checks for React components inside the children, and if there are any, it'll skip the truncation. Closing this issue as that (React components used as children) looks to be the reason for the originally reported error. |
This issue is still occurring when width is less 300px. |
Hey @agduyaguit, can you post a link to codesanbox with a repro case? Thanks! |
hi @patrik-piskay , Here is the test data I used to replicate the issue:
|
I am facing same problem. Any update for this? |
Can you post your case example on codesanbox @nvuhung? |
My code is same as @agduyaguit |
I am also experiencing this issue; the package is not usable because it crashes the whole app. Is there a way to throttle the resize event? I'm passing simple DOM HTML into the component (not complex React components). |
WorkaroundI developed a workaround for this issue until it is fixed. This module is overall great, but clearly this problem is complex. Using an error boundary with fallbacks, we can render the unabridged markup instead of crashing.
💡 ErrorBoundary componentimport React from 'react';
interface State {
hasError: boolean;
}
interface Props {
children: React.ReactNode;
className?: string;
fallback?: React.ReactNode;
fallbackHtml?: string;
name: string;
}
class ErrorBoundary extends React.Component<Props, State> {
state: State = {
hasError: false,
};
componentDidCatch(error: any, info: any) {
const { name } = this.props;
this.setState({ hasError: true });
log(
`%cCaught "${name}" ErrorBoundary`,
'color: #c0392b; font-weight: 600;',
);
log('%s', error);
log('%j', info);
}
render() {
const { hasError } = this.state;
const { children, fallback, fallbackHtml } = this.props;
if (hasError) {
if (fallbackHtml) {
return <div dangerouslySetInnerHTML={{ __html: fallbackHtml }} />;
}
if (fallback) {
return fallback;
}
return (
<div>
An unexpected error occurred.
<br />
<br />
<a href=".">Reload page</a>.
</div>
);
}
return children;
}
}
export default ErrorBoundary;
Apply boundary to
|
Hey @drewlustro, can you post a codesanbox of your specific issue? we need as many failing cases as possible because, as you said, it's a complex problem and sometimes it's the markup that's passed into the component that's causing it, like Specifically, I'd be interested to see what |
Is there any progress? I am facing the same issue. |
Hi @svobik7, any chance you can provide a repro case (using codesanbox or some other, similar online tool)? It'll be easier to spot the issue is that way. |
Hi @patrik-piskay, unfortunately my repo is private. But I discovered that error happend only when content wrapper width is < 300px. Maybe it will help. As I was pushed to solve this problem I had to use another library. |
I can't ever seem to get past this error:
Currently the library seems unusable =/ Not sure how to guard against it within the
componentDidUpdate
lifecycle hook.The text was updated successfully, but these errors were encountered: