Skip to content
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

Re-Rendering the code and creating multiple nested span when there is an action in the page #22

Open
laksmaria opened this issue Sep 7, 2016 · 9 comments

Comments

@laksmaria
Copy link

Re-Rendering the code and creating multiple nested span when there is an action in the page

for ex: if there is an button click and the block getting re-rendered and adding many nested span for the existing span elements

@akiran
Copy link
Owner

akiran commented Sep 7, 2016

Can you give a code sample to replicate the issue?

@alasdairhurst
Copy link

alasdairhurst commented Oct 3, 2016

I can replicate this. Every time the component is re-rendered it gets nested one step deeper. Create a component which uses react-highlight to render a string prop, render it inside another component, alongside a button or some other event. On that event modify the string and see the issue.

screen shot 2016-10-03 at 17 14 43

@scragg0x
Copy link

scragg0x commented May 1, 2017

If you are using Highlight inside of an iterator such as map or a for, be sure to set the key with some identifier. Or if you know it will always be different, set the key with Date.now() in it. Here is a sample...

  const rows = _.map(data, (val, key) => {
    return (
      <tr key={`logitem-${key}-${Date.now()}`}>
        <td>{key}</td>
        <td><Highlight className="xml">{val}</Highlight></td>
      </tr>
    );
  });

  return (
    <table className="log-item table table-bordered">
      <tbody>{rows}</tbody>
    </table>
  );

@troelsim
Copy link

Here is an example demonstrating the issue

class Nestor extends React.Component {
    componentWillMount() {
        this.setState({times_rendered: 1});
        this.timer = setInterval(() => this.setState({times_rendered: this.state.times_rendered + 1}), 5000)
    }

    render() {
        return <div>
            <Highlight>{`Rendered ${this.state.times_rendered} times`}</Highlight>
            <Highlight>static text</Highlight>
        </div>;
    }
}

When the content dynamically changes on each update, there is no problem. But if the Highlight component re-renders without its content changing, we get nested <span>s. In this example, the second highlight component gets nested one level deeper every 5 seconds.

I solve this by making sure only to re-render a component when the content actually changes. But react-highlight should not behave this way.

I suppose it is a consequence of altering the DOM elements rendered by React. My guess is that even if React determines that nothing changes and there is no reason to manipulate a given DOM element, react-highlight will grab it and wrap it in a <span> anyway.

@juancabrera
Copy link

Had the same issue, I fixed it by making sure the component doesn't get re-rendered. But I also think react-highlight should not keep nesting for every re-render.

@yankopetrov
Copy link

@scragg0x Date.now() made the trick for me. 10x

@CodyFitzpatrick
Copy link

Having the same issue unfortunately.

@troelsim or @juancabrera, by any chance can you please post here what adjustments you made to ensure that <Highlight> components don't re-render with every re-render of their parent component?

@CodyFitzpatrick
Copy link

Update here, Fix (or should I say "Hack") below:

I followed @scragg0x recommendation and essentially included a Date.now() portion in the value of the key of a parent element (not component) of the <Highlight> component.

For example:

<div className="html-container" 
     key={"html-for-element-" + elementDetails.id + "-" + Date.now().toString()}
>
     <span>HTML:</span>
     <Highlight
         className='html'
         {elementDetails.element_html}
     </Highlight>
</div>

With that said, I definitely agree that react-highlight should not keep nesting for every re-render!

@jsejcksn jsejcksn mentioned this issue Aug 14, 2019
@jsejcksn
Copy link

Another way to fix this is to return the <Highlight /> component from another component which is defined via React.memo() (for a function component) or React.PureComponent() (for a class component).

const HighlightStable = React.memo(props => <Highlight {...props}></Highlight>);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants