How React's diffing algorithm works with a list of elements?










1















UPD: I used React Dev Tools with Highlight Updates which seems to highlight each render() method call



I've written a simple React App which works the next way:



  1. It has a button and a list of numbers

  2. After clicking the button it adds a new number to the bottom of the list increased by 1 from the previous one

The problem is that React updates all list elements each time even when I use key property. I know that this problem can be solved by using PureComponents class or self-implemented shouldComponentUpdate()



Why React updates all list elements if they are not changed? I though that React uses special diffing algorithm for comparing elements and it should have worked, but now I see that it works not as I expected.



Could any body explain why React's diffing algorithm doesn't work in this case?



class App extends Component 
constructor(props)
super(props);

this.state =
numbers:


this.handleButtonClick = this.handleButtonClick.bind(this);


handleButtonClick()
const numbers = this.state.numbers;
const length = this.state.numbers.length ;
const newNumber = length > 0 ? numbers[length - 1] + 1 : 0;

this.setState(
numbers: [...numbers, newNumber]
)


render()
return (
<div>
<button onClick=this.handleButtonClick>Add</button>
<NumbersList numbers=this.state.numbers />
</div>
);




class NumbersList extends Component
render()
return (
<ul>

this.props.numbers.map((number) => <NumberItem key=number number=number />)

</ul>
)



class NumberItem extends Component
render()
return (
<li>this.props.number</li>
)











share|improve this question



















  • 1





    Are your keys unique?

    – Sergiu Paraschiv
    Nov 12 '18 at 12:58











  • @SergiuParaschiv Yes, they are. I don't think that it's a bug of my app

    – Roman Roman
    Nov 12 '18 at 13:00






  • 1





    jsfiddle.net/zphfaoy4 - Using dev tools in Chrome on the Elements tab I don't see any DOM changes other than new <li> elements being added. Either I don't understand the question or I cannot reproduce this.

    – Sergiu Paraschiv
    Nov 12 '18 at 13:05











  • @SergiuParaschiv If try to use the React devtool extension and you turn on "Highlighting update" there it will show you that all elements are updated

    – Roman Roman
    Nov 12 '18 at 13:11






  • 1





    Unfortunately React Dev Tools don't work in jsfiddle. But I am pretty sure that what the inspector shows is correct. Add a "break on subtree modifications" breakpoint on the <ul> and look through the process. You'll find that only the new <li> insertion happens. I guess React Dev Tools does something unexpected here.

    – Sergiu Paraschiv
    Nov 12 '18 at 13:18















1















UPD: I used React Dev Tools with Highlight Updates which seems to highlight each render() method call



I've written a simple React App which works the next way:



  1. It has a button and a list of numbers

  2. After clicking the button it adds a new number to the bottom of the list increased by 1 from the previous one

The problem is that React updates all list elements each time even when I use key property. I know that this problem can be solved by using PureComponents class or self-implemented shouldComponentUpdate()



Why React updates all list elements if they are not changed? I though that React uses special diffing algorithm for comparing elements and it should have worked, but now I see that it works not as I expected.



Could any body explain why React's diffing algorithm doesn't work in this case?



class App extends Component 
constructor(props)
super(props);

this.state =
numbers:


this.handleButtonClick = this.handleButtonClick.bind(this);


handleButtonClick()
const numbers = this.state.numbers;
const length = this.state.numbers.length ;
const newNumber = length > 0 ? numbers[length - 1] + 1 : 0;

this.setState(
numbers: [...numbers, newNumber]
)


render()
return (
<div>
<button onClick=this.handleButtonClick>Add</button>
<NumbersList numbers=this.state.numbers />
</div>
);




class NumbersList extends Component
render()
return (
<ul>

this.props.numbers.map((number) => <NumberItem key=number number=number />)

</ul>
)



class NumberItem extends Component
render()
return (
<li>this.props.number</li>
)











share|improve this question



















  • 1





    Are your keys unique?

    – Sergiu Paraschiv
    Nov 12 '18 at 12:58











  • @SergiuParaschiv Yes, they are. I don't think that it's a bug of my app

    – Roman Roman
    Nov 12 '18 at 13:00






  • 1





    jsfiddle.net/zphfaoy4 - Using dev tools in Chrome on the Elements tab I don't see any DOM changes other than new <li> elements being added. Either I don't understand the question or I cannot reproduce this.

    – Sergiu Paraschiv
    Nov 12 '18 at 13:05











  • @SergiuParaschiv If try to use the React devtool extension and you turn on "Highlighting update" there it will show you that all elements are updated

    – Roman Roman
    Nov 12 '18 at 13:11






  • 1





    Unfortunately React Dev Tools don't work in jsfiddle. But I am pretty sure that what the inspector shows is correct. Add a "break on subtree modifications" breakpoint on the <ul> and look through the process. You'll find that only the new <li> insertion happens. I guess React Dev Tools does something unexpected here.

    – Sergiu Paraschiv
    Nov 12 '18 at 13:18













1












1








1








UPD: I used React Dev Tools with Highlight Updates which seems to highlight each render() method call



I've written a simple React App which works the next way:



  1. It has a button and a list of numbers

  2. After clicking the button it adds a new number to the bottom of the list increased by 1 from the previous one

The problem is that React updates all list elements each time even when I use key property. I know that this problem can be solved by using PureComponents class or self-implemented shouldComponentUpdate()



Why React updates all list elements if they are not changed? I though that React uses special diffing algorithm for comparing elements and it should have worked, but now I see that it works not as I expected.



Could any body explain why React's diffing algorithm doesn't work in this case?



class App extends Component 
constructor(props)
super(props);

this.state =
numbers:


this.handleButtonClick = this.handleButtonClick.bind(this);


handleButtonClick()
const numbers = this.state.numbers;
const length = this.state.numbers.length ;
const newNumber = length > 0 ? numbers[length - 1] + 1 : 0;

this.setState(
numbers: [...numbers, newNumber]
)


render()
return (
<div>
<button onClick=this.handleButtonClick>Add</button>
<NumbersList numbers=this.state.numbers />
</div>
);




class NumbersList extends Component
render()
return (
<ul>

this.props.numbers.map((number) => <NumberItem key=number number=number />)

</ul>
)



class NumberItem extends Component
render()
return (
<li>this.props.number</li>
)











share|improve this question
















UPD: I used React Dev Tools with Highlight Updates which seems to highlight each render() method call



I've written a simple React App which works the next way:



  1. It has a button and a list of numbers

  2. After clicking the button it adds a new number to the bottom of the list increased by 1 from the previous one

The problem is that React updates all list elements each time even when I use key property. I know that this problem can be solved by using PureComponents class or self-implemented shouldComponentUpdate()



Why React updates all list elements if they are not changed? I though that React uses special diffing algorithm for comparing elements and it should have worked, but now I see that it works not as I expected.



Could any body explain why React's diffing algorithm doesn't work in this case?



class App extends Component 
constructor(props)
super(props);

this.state =
numbers:


this.handleButtonClick = this.handleButtonClick.bind(this);


handleButtonClick()
const numbers = this.state.numbers;
const length = this.state.numbers.length ;
const newNumber = length > 0 ? numbers[length - 1] + 1 : 0;

this.setState(
numbers: [...numbers, newNumber]
)


render()
return (
<div>
<button onClick=this.handleButtonClick>Add</button>
<NumbersList numbers=this.state.numbers />
</div>
);




class NumbersList extends Component
render()
return (
<ul>

this.props.numbers.map((number) => <NumberItem key=number number=number />)

</ul>
)



class NumberItem extends Component
render()
return (
<li>this.props.number</li>
)








javascript reactjs






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 '18 at 13:34







Roman Roman

















asked Nov 12 '18 at 12:54









Roman RomanRoman Roman

30711




30711







  • 1





    Are your keys unique?

    – Sergiu Paraschiv
    Nov 12 '18 at 12:58











  • @SergiuParaschiv Yes, they are. I don't think that it's a bug of my app

    – Roman Roman
    Nov 12 '18 at 13:00






  • 1





    jsfiddle.net/zphfaoy4 - Using dev tools in Chrome on the Elements tab I don't see any DOM changes other than new <li> elements being added. Either I don't understand the question or I cannot reproduce this.

    – Sergiu Paraschiv
    Nov 12 '18 at 13:05











  • @SergiuParaschiv If try to use the React devtool extension and you turn on "Highlighting update" there it will show you that all elements are updated

    – Roman Roman
    Nov 12 '18 at 13:11






  • 1





    Unfortunately React Dev Tools don't work in jsfiddle. But I am pretty sure that what the inspector shows is correct. Add a "break on subtree modifications" breakpoint on the <ul> and look through the process. You'll find that only the new <li> insertion happens. I guess React Dev Tools does something unexpected here.

    – Sergiu Paraschiv
    Nov 12 '18 at 13:18












  • 1





    Are your keys unique?

    – Sergiu Paraschiv
    Nov 12 '18 at 12:58











  • @SergiuParaschiv Yes, they are. I don't think that it's a bug of my app

    – Roman Roman
    Nov 12 '18 at 13:00






  • 1





    jsfiddle.net/zphfaoy4 - Using dev tools in Chrome on the Elements tab I don't see any DOM changes other than new <li> elements being added. Either I don't understand the question or I cannot reproduce this.

    – Sergiu Paraschiv
    Nov 12 '18 at 13:05











  • @SergiuParaschiv If try to use the React devtool extension and you turn on "Highlighting update" there it will show you that all elements are updated

    – Roman Roman
    Nov 12 '18 at 13:11






  • 1





    Unfortunately React Dev Tools don't work in jsfiddle. But I am pretty sure that what the inspector shows is correct. Add a "break on subtree modifications" breakpoint on the <ul> and look through the process. You'll find that only the new <li> insertion happens. I guess React Dev Tools does something unexpected here.

    – Sergiu Paraschiv
    Nov 12 '18 at 13:18







1




1





Are your keys unique?

– Sergiu Paraschiv
Nov 12 '18 at 12:58





Are your keys unique?

– Sergiu Paraschiv
Nov 12 '18 at 12:58













@SergiuParaschiv Yes, they are. I don't think that it's a bug of my app

– Roman Roman
Nov 12 '18 at 13:00





@SergiuParaschiv Yes, they are. I don't think that it's a bug of my app

– Roman Roman
Nov 12 '18 at 13:00




1




1





jsfiddle.net/zphfaoy4 - Using dev tools in Chrome on the Elements tab I don't see any DOM changes other than new <li> elements being added. Either I don't understand the question or I cannot reproduce this.

– Sergiu Paraschiv
Nov 12 '18 at 13:05





jsfiddle.net/zphfaoy4 - Using dev tools in Chrome on the Elements tab I don't see any DOM changes other than new <li> elements being added. Either I don't understand the question or I cannot reproduce this.

– Sergiu Paraschiv
Nov 12 '18 at 13:05













@SergiuParaschiv If try to use the React devtool extension and you turn on "Highlighting update" there it will show you that all elements are updated

– Roman Roman
Nov 12 '18 at 13:11





@SergiuParaschiv If try to use the React devtool extension and you turn on "Highlighting update" there it will show you that all elements are updated

– Roman Roman
Nov 12 '18 at 13:11




1




1





Unfortunately React Dev Tools don't work in jsfiddle. But I am pretty sure that what the inspector shows is correct. Add a "break on subtree modifications" breakpoint on the <ul> and look through the process. You'll find that only the new <li> insertion happens. I guess React Dev Tools does something unexpected here.

– Sergiu Paraschiv
Nov 12 '18 at 13:18





Unfortunately React Dev Tools don't work in jsfiddle. But I am pretty sure that what the inspector shows is correct. Add a "break on subtree modifications" breakpoint on the <ul> and look through the process. You'll find that only the new <li> insertion happens. I guess React Dev Tools does something unexpected here.

– Sergiu Paraschiv
Nov 12 '18 at 13:18












2 Answers
2






active

oldest

votes


















1














The Javascript/React side uses shouldComponentUpdate to determine if it should rerender. This defaults to true and will rerender the component any time that there is a state change.



https://reactjs.org/docs/react-component.html#shouldcomponentupdate



Using this rerendered virtual representation of your app, it uses this https://reactjs.org/docs/reconciliation.html#the-diffing-algorithm to reconcile your virtualDOM with the real DOM






share|improve this answer























  • I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.

    – Roman Roman
    Nov 12 '18 at 13:36











  • The render method is called when shouldComponentUpdate returns true. shouldComponentUpdate runs when state changes. That is independent of the actual dom being updated. The only way to affect that is to return false from shouldComponentUpdate, which should only be overridded when there is a serious performance issue.

    – Austio
    Nov 12 '18 at 13:46


















0














Have you tried:



this.setState(numbers[index-1]: newNumber)?



Your code here:



this.setState(
numbers: [...numbers, newNumber]
)


reads to me as a replacement of the numbers array and not an update of it.






share|improve this answer






















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262625%2fhow-reacts-diffing-algorithm-works-with-a-list-of-elements%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    The Javascript/React side uses shouldComponentUpdate to determine if it should rerender. This defaults to true and will rerender the component any time that there is a state change.



    https://reactjs.org/docs/react-component.html#shouldcomponentupdate



    Using this rerendered virtual representation of your app, it uses this https://reactjs.org/docs/reconciliation.html#the-diffing-algorithm to reconcile your virtualDOM with the real DOM






    share|improve this answer























    • I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.

      – Roman Roman
      Nov 12 '18 at 13:36











    • The render method is called when shouldComponentUpdate returns true. shouldComponentUpdate runs when state changes. That is independent of the actual dom being updated. The only way to affect that is to return false from shouldComponentUpdate, which should only be overridded when there is a serious performance issue.

      – Austio
      Nov 12 '18 at 13:46















    1














    The Javascript/React side uses shouldComponentUpdate to determine if it should rerender. This defaults to true and will rerender the component any time that there is a state change.



    https://reactjs.org/docs/react-component.html#shouldcomponentupdate



    Using this rerendered virtual representation of your app, it uses this https://reactjs.org/docs/reconciliation.html#the-diffing-algorithm to reconcile your virtualDOM with the real DOM






    share|improve this answer























    • I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.

      – Roman Roman
      Nov 12 '18 at 13:36











    • The render method is called when shouldComponentUpdate returns true. shouldComponentUpdate runs when state changes. That is independent of the actual dom being updated. The only way to affect that is to return false from shouldComponentUpdate, which should only be overridded when there is a serious performance issue.

      – Austio
      Nov 12 '18 at 13:46













    1












    1








    1







    The Javascript/React side uses shouldComponentUpdate to determine if it should rerender. This defaults to true and will rerender the component any time that there is a state change.



    https://reactjs.org/docs/react-component.html#shouldcomponentupdate



    Using this rerendered virtual representation of your app, it uses this https://reactjs.org/docs/reconciliation.html#the-diffing-algorithm to reconcile your virtualDOM with the real DOM






    share|improve this answer













    The Javascript/React side uses shouldComponentUpdate to determine if it should rerender. This defaults to true and will rerender the component any time that there is a state change.



    https://reactjs.org/docs/react-component.html#shouldcomponentupdate



    Using this rerendered virtual representation of your app, it uses this https://reactjs.org/docs/reconciliation.html#the-diffing-algorithm to reconcile your virtualDOM with the real DOM







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 12 '18 at 13:03









    AustioAustio

    4,5171228




    4,5171228












    • I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.

      – Roman Roman
      Nov 12 '18 at 13:36











    • The render method is called when shouldComponentUpdate returns true. shouldComponentUpdate runs when state changes. That is independent of the actual dom being updated. The only way to affect that is to return false from shouldComponentUpdate, which should only be overridded when there is a serious performance issue.

      – Austio
      Nov 12 '18 at 13:46

















    • I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.

      – Roman Roman
      Nov 12 '18 at 13:36











    • The render method is called when shouldComponentUpdate returns true. shouldComponentUpdate runs when state changes. That is independent of the actual dom being updated. The only way to affect that is to return false from shouldComponentUpdate, which should only be overridded when there is a serious performance issue.

      – Austio
      Nov 12 '18 at 13:46
















    I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.

    – Roman Roman
    Nov 12 '18 at 13:36





    I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.

    – Roman Roman
    Nov 12 '18 at 13:36













    The render method is called when shouldComponentUpdate returns true. shouldComponentUpdate runs when state changes. That is independent of the actual dom being updated. The only way to affect that is to return false from shouldComponentUpdate, which should only be overridded when there is a serious performance issue.

    – Austio
    Nov 12 '18 at 13:46





    The render method is called when shouldComponentUpdate returns true. shouldComponentUpdate runs when state changes. That is independent of the actual dom being updated. The only way to affect that is to return false from shouldComponentUpdate, which should only be overridded when there is a serious performance issue.

    – Austio
    Nov 12 '18 at 13:46













    0














    Have you tried:



    this.setState(numbers[index-1]: newNumber)?



    Your code here:



    this.setState(
    numbers: [...numbers, newNumber]
    )


    reads to me as a replacement of the numbers array and not an update of it.






    share|improve this answer



























      0














      Have you tried:



      this.setState(numbers[index-1]: newNumber)?



      Your code here:



      this.setState(
      numbers: [...numbers, newNumber]
      )


      reads to me as a replacement of the numbers array and not an update of it.






      share|improve this answer

























        0












        0








        0







        Have you tried:



        this.setState(numbers[index-1]: newNumber)?



        Your code here:



        this.setState(
        numbers: [...numbers, newNumber]
        )


        reads to me as a replacement of the numbers array and not an update of it.






        share|improve this answer













        Have you tried:



        this.setState(numbers[index-1]: newNumber)?



        Your code here:



        this.setState(
        numbers: [...numbers, newNumber]
        )


        reads to me as a replacement of the numbers array and not an update of it.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 12 '18 at 13:18









        kbarkbar

        427




        427



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262625%2fhow-reacts-diffing-algorithm-works-with-a-list-of-elements%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Use pre created SQLite database for Android project in kotlin

            Darth Vader #20

            Ondo