diff --git a/docs/performance/reduce-reconciliation.md b/docs/performance/reduce-reconciliation.md index 8ece729f..3441f630 100644 --- a/docs/performance/reduce-reconciliation.md +++ b/docs/performance/reduce-reconciliation.md @@ -5,13 +5,14 @@ In all likelihood, the primary source of performance gains for your app will com ## `shouldUpdate` Lifecycle Method When a Roact Component's state or props change, it will call the Component's `shouldUpdate` method to determine whether or not to re-render it. The default implementation will always return true. + ```lua function Component:shouldUpdate(newProps, newState) return true end ``` -If you have a more complex component that only needs to re-render in certain situations, you can either use `PureComponent` (discussed below) or implement your own `shouldUpdate` and return `false` in any case where an update is not required. +Suppose you have a more complex component that only needs to re-render in certain situations. In that case, you can either use `PureComponent` (discussed below) or implement your own `shouldUpdate` and return `false` in any case where an update is not required. !!! warning Manually implementing `shouldUpdate` is *dangerous*! If done carelessly, it can easily create confusing or subtle bugs. @@ -22,6 +23,7 @@ If you have a more complex component that only needs to re-render in certain sit One common implementation of `shouldUpdate` is to do a shallow comparison between current and previous props and state. `Roact` provides an extension of `Roact.Component` called `Roact.PureComponent` that uses this implementation. Let's use the following example: + ```lua local Item = Roact.Component:extend("Item") @@ -61,12 +63,12 @@ function Inventory:render() Size = UDim2.new(0, 200, 0, 400) }, itemList) end - ``` In the above example, adding a new item to the `items` prop of the `Inventory` would cause all of the child `Item` elements to re-render, even if they haven't changed at all. This means if you add an item to an `Inventory` that already has 5 items, the result will be 6 renders of the `Item` component. Lets change `Item` to a `PureComponent`: + ```lua local Item = Roact.PureComponent:extend("Item") ``` @@ -82,9 +84,10 @@ Now, if we add a new item to the end of the `Inventory` or change something abou Another performance improvement we can make is to use stable, unique keys to refer to our child elements. -When the list that we pass into the `Inventory` component changes, Roact updates our Roblox UI by adjusting the properties of each Roblox Instance according to the new list of elements. +For example, suppose a list we pass into the `Inventory` component changes. Roact would update the Roblox UI by adjusting the properties of each Roblox Instance according to the new list of elements. For example, let's suppose our list of items is as follows: + ```lua { { id = "sword", icon = swordIcon }, -- [1] @@ -93,6 +96,7 @@ For example, let's suppose our list of items is as follows: ``` If we add a new item to the beginning, then we'll end up with a list like this: + ```lua { { id = "potion", icon = potionIcon } -- [1] @@ -103,7 +107,7 @@ If we add a new item to the beginning, then we'll end up with a list like this: When Roact updates the underlying `ImageLabel` objects, it will need to change their icons so that the item at `[1]` has the potion icon, the item at `[2]` has the sword icon, and a new `ImageLabel` is added at `[3]` with the shield icon. -We'd like for Roact to know that the new item was added at `[1]` and that the sword and shield items simply moved down in the list. That way it can adjust their LayoutOrder properties and let the Roblox UI system resolve the rest. +We want Roact to know that the new item was added at `[1]` and that the sword and shield items moved down in the list. That way, it can adjust their LayoutOrder properties and let the Roblox UI system resolve the rest. So let's fix it! We'll make our list of `Item` elements use the item's id for its keys instead of the indexes in the `items` list: @@ -132,7 +136,7 @@ function Inventory:render() end ``` -Now the list of children is keyed by the stable, unique id of the item data. Their positions can change according to their LayoutOrder, but no other properties on the item need to be updated. When we add the third element to the list, Roact will set the `LayoutOrder` property on for each `ImageLabel` and only set the `Image` property on the newly added one! +Now the list of children is keyed by the stable, unique id of the item data. Their positions can change according to their LayoutOrder, but no other item properties need to be updated. When we add the third element to the list, Roact will set the `LayoutOrder` property on each `ImageLabel` and only set the `Image` property on the newly added one! !!! info Switching to static keys might seem insignificant for *this* example, but if our `Item` component becomes more complicated and our inventory gets bigger, it can make a significant difference!