react-truncate: text is broken wrongly and randomly with webpack

I want 4 lines for example and i get 5 with an extra one with the ellipsis, the div around is just to see if it was that but the issue remains

<div>
     <h2 className="title">
           <Truncate lines={4}>
                {titleToTruncate}
            </Truncate>
     </h2>
</div>

Lorem ipsum dolor sit amet,Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet, Lorem ipsum dolor sit amet,Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dui …

something like that im getting, and is kind of random with the hot reload sometimes is like that, sometimes different, makes it not really reliable, I tried but will have to switch to another component.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 19 (6 by maintainers)

Most upvoted comments

If you don’t need to be able to resize the container, you can add a css rule like that:

.your-truncate-class > span {
    white-space: nowrap;
}

Of course the line breaks will still be calculated wrong, but at least the lines will have the same width and are aligned (and hopefully not break out of your design).

Thank you for reporting anyway, I am sure other people might bump into that as well.

Closing this issue since this is out of the scope of the component, unfortunatly.

I might come back to this issue when I have a demo playground running for this repository.

I wrote a (sorta) elegant solution to this that forces truncate to rerender itself upon font face load completion. You’ll need recompose (or write a hoc that renders a component itself) & fontfaceonload

import { lifecycle } from 'recompose';
import onFontFaceLoad from 'fontfaceonload';

// little HOC that force updates it's contents once a font face is loaded

export default (fontFace) =>
    lifecycle({
        componentDidMount () {
            onFontFaceLoad(fontFace, {
                success: () => {
                    setTimeout(() => this.forceUpdate(), 0);
                }
            });
        },
    });

Then, from the component that consumes the library:

import withFontLoadRender from ...

const UpdatingTruncate = withFontLoadRender('YourFontFamily')(Truncate);

export default () => (
    <UpdatingTruncate lines={2}>Text to truncate</UpdatingTruncate>
)

(I have no idea why the setTimeout is needed, but it is)

Hi. I solve this creating a ReadMore (as in the examples) using the document.fonts.ready html event. I use the ready state to catch when the fonts are already loaded and to set expanded=false.

import { useState, useEffect } from 'react';
import Truncate from 'react-truncate';

export default function ReadMore({ lines, children }) {

    const [expanded, setExpanded] = useState(true);
    const [truncated, setTruncated] = useState(false);
    const [ready, setReady] = useState(false);

    function handleTruncate(t) {
        if (truncated !== t) setTruncated(t);
    }

    function toggleLines(e) {
        e.preventDefault();
        setExpanded(!expanded);
    }

    useEffect(() => {
        
        if (ready) return;

        document.fonts.ready.then(function () {
            setReady(true);
            setExpanded(false);
        });
    });

    return (
        <>
            <Truncate
                lines={!expanded && lines}
                ellipsis={<span>...  <button className="readMore" onClick={toggleLines}>Ver Más</button></span>} onTruncate={handleTruncate}>
                {children}
            </Truncate>
            {!truncated && expanded && (
                <span>...  <button className="readMore" onClick={toggleLines}>Ver Menos</button></span>
            )}
        </>
    )
}

Suggested fix: Use font-family: ‘Custom Font’, ‘Courier New’, sans-serif in order to prevent the weird line breaking when the custom font is loaded and increases in width, as Truncate works before the font loads. Courier New will need to be wider than the custom font.

Thanks Pablo for your help, very much!

If this was the cause, it would be a pretty hard problem to solve within this module.

I could do some arbitrary canvas checks before and after rendering and see if they give the same width. However, this would also not guarantee that it works 100% of the time, just reduce the probability of failure.

My advise here is to put your stylesheet into the page head and block page rendering until it’s done loading and make sure that your font file is served as fast as possible (CDN, cached).