How React's diffing algorithm works with a list of elements?
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:
- It has a button and a list of numbers
- 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
|
show 1 more comment
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:
- It has a button and a list of numbers
- 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
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
|
show 1 more comment
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:
- It has a button and a list of numbers
- 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
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:
- It has a button and a list of numbers
- 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
javascript reactjs
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
|
show 1 more comment
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
|
show 1 more comment
2 Answers
2
active
oldest
votes
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
I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.
– Roman Roman
Nov 12 '18 at 13:36
Therender
method is called whenshouldComponentUpdate
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
add a comment |
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.
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.
– Roman Roman
Nov 12 '18 at 13:36
Therender
method is called whenshouldComponentUpdate
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
add a comment |
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
I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.
– Roman Roman
Nov 12 '18 at 13:36
Therender
method is called whenshouldComponentUpdate
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
add a comment |
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
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
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
Therender
method is called whenshouldComponentUpdate
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
add a comment |
I used React Dev Tools with Highlight Updates which seems to highlight each render() method call.
– Roman Roman
Nov 12 '18 at 13:36
Therender
method is called whenshouldComponentUpdate
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
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 12 '18 at 13:18
kbarkbar
427
427
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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