React 16.4 included a [bugfix for getDerivedStateFromProps](/blog/2018/05/23/react-v-16-4.html#bugfix-for-getderivedstatefromprops) which made some existing bugs in React components reproduce more consistently. We carefully considered this change, and although we believe it was the right decision, we apologize for any inconvenience it caused. In this post, we will explain some common anti-patterns with derived state, and the preferred alternatives to each.
React 16.4 included a [bugfix for getDerivedStateFromProps](/blog/2018/05/23/react-v-16-4.html#bugfix-for-getderivedstatefromprops) which caused some existing bugs in React components to reproduce more consistently. If this release exposed a case where your application was using an anti-pattern and didn't work properly after the fix, we're sorry for the churn. In this post, we will explain some common anti-patterns with derived state and our preferred alternatives.
The lifecycle `componentWillReceiveProps`has been around for a long time. Until recently, it was the only way to update state in response to a change in props without triggering an additional render. In version 16.3, [we introduced a replacement lifecycle, `getDerivedStateFromProps`](/blog/2018/03/29/react-v-16-3.html#component-lifecycle-changes), that served the same purpose. However, as we've helped people migrate their components to the new lifecycle, we've uncovered some common anti-patterns for derived state that result in subtle and confusing bugs.
For a long time, the lifecycle `componentWillReceiveProps` was the only way to update state in response to a change in props without an additional render. In version 16.3, [we introduced a replacement lifecycle, `getDerivedStateFromProps`](/blog/2018/03/29/react-v-16-3.html#component-lifecycle-changes) to solve the same use cases in a safer way. At the same time, we've realized that people have many misconceptions about how to use both methods, and we've found anti-patterns that result in subtle and confusing bugs. The `getDerivedStateFromProps` bugfix in 16.4 [makes derived state more predictable](https://github.com/facebook/react/issues/12898), so the results of misusing it are easier to notice.
> Note
>
> The anti-patterns described in this post apply to both `componentWillReceiveProps` and `getDerivedStateFromProps`!
> All of the anti-patterns described in this post apply to both the older `componentWillReceiveProps` and the newer `getDerivedStateFromProps`.
In 16.4, we released a bugfix that [makes derived state behavior more predictable](https://github.com/facebook/react/issues/12898) so the results of misusing it are easier to notice. This blog post will guide you through when derived state should be used, and when there are better alternatives.
We'll cover the following topics:
* [How to decide if you should use derived state](#how-to-decide-if-you-should-use-derived-state)
This blog post will cover the following topics:
* [When to use derived state](#when-to-use-derived-state)
* [Common bugs when using derived state](#common-bugs-when-using-derived-state)
* [Anti-pattern: Mirroring props in state](#anti-pattern-mirroring-props-in-state)
* [Anti-pattern: Unconditionally copying props to state](#anti-pattern-unconditionally-copying-props-to-state)
* [Anti-pattern: Erasing state when props change](#anti-pattern-erasing-state-when-props-change)
* [Preferred solutions](#preferred-solutions)
* [What about memoization?](#what-about-memoization)
## How to Decide if You Should Use Derived State
`getDerivedStateFromProps` exists for only one purpose. It enables a component to update its internal state as the result of **changes in props**. This distinction is important. All problems with derived state that we have seen can be ultimately reduced to either (1) unconditionally updating state from props or (2) updating state whenever props and state don't match. (We'll go over both in more detail below.)
## When to Use Derived State
So what does it mean to update state as the result of changes in props? Our previous blog post provided some examples, like [managing the current scroll direction based on an offset prop](/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props) or [loading external data specified by a source prop](/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data-when-props-change). We did not provide many examples, because as a general rule, **derived state should be used sparingly**.
`getDerivedStateFromProps` exists for only one purpose. It enables a component to update its internal state as the result of **changes in props**. Our previous blog post provided some examples, like [recording the current scroll direction based on a changing offset prop](/blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props) or [loading external data specified by a source prop](/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data-when-props-change).
If you're not sure about whether your component should use derived state, here are some questions to ask yourself:
* Is the state **derived** from props (as opposed to just mirroring it)?
* Is the state update specifically triggered by a **props change** (and not just the current props value)?
We did not provide many examples, because as a general rule, **derived state should be used sparingly**. All problems with derived state that we have seen can be ultimately reduced to either (1) unconditionally updating state from props or (2) updating state whenever props and state don't match. (We'll go over both in more detail below.)
If your answer to either of the above questions is “no” (which is almost always the case) then there are better patterns to use! We’ll cover them below.
* If you're using derived state to memoize some computation based only on the current props, you don't need derived state. See [What about memoization?](#what-about-memoization) below.
* If you're updating derived state unconditionally or updating it whenever props and state don't match, your component likely resets its state too frequently. Read on for more details.
## Common Bugs When Using Derived State
The terms ["controlled"](/docs/forms.html#controlled-components) and ["uncontrolled"](/docs/uncontrolled-components.html) are often used to refer to form components, but they can also be used to describe where a component's data lives. Data that is passed in as props can be thought of as **controlled** (because the parent component _controls_ that data). Data that exists only in internal state can be thought of as **uncontrolled** (because the parent can't directly change it).
The terms ["controlled"](/docs/forms.html#controlled-components) and ["uncontrolled"](/docs/uncontrolled-components.html) usually refer to form inputs, but they can also describe where any component's data lives. Data passed in as props can be thought of as **controlled** (because the parent component _controls_ that data). Data that exists only in internal state can be thought of as **uncontrolled** (because the parent can't directly change it).
The most common mistake with derived state is mixing these two. In other words, when props control a value in state that is also updated by `setState` calls. This may sound similar to the [external data loading example](/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data-when-props-change) mentioned above, but it's different in a few important ways.
In the loading example, there is a clear source of truth for both the "source" prop and the "loading" state. When the source prop changes, the loading state should **always** be overridden. Conversely the state should only be overridden when the prop **changes** and should otherwise be managed by the component.
The most common mistake with derived state is mixing these two; when a derived state value is also updated by `setState` calls, there isn't a single source of truth for the data. The [external data loading example](/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data-when-props-change) mentioned above may sound similar, but it's different in a few important ways. In the loading example, there is a clear source of truth for both the "source" prop and the "loading" state. When the source prop changes, the loading state should **always** be overridden. Conversely, the state is overridden only when the prop **changes** and is otherwise managed by the component.
Problems arise when any of these constraints are changed. This typically comes in two forms. Let's take a look at both.
### Anti-pattern: Mirroring props in state
A common misconception is that `getDerivedStateFromProps` and `componentWillReceiveProps` are only called when props "change". However, these lifecycles will be called any time a parent component re-renders, regardless of props changes. Because of this, it is (and has always been) unsafe to _unconditionally_ override state using either of these lifecycles. **Doing so will cause state updates to be lost.**
### Anti-pattern: Unconditionally copying props to state
This was less obvious before React 16.4, because the behavior depended on when a parent component re-rendered. This made it possible to overlook potential bugs when testing locally. To make things more consistent and predictable, we made `getDerivedStateFromProps` fire for renders caused by `setState` and `forceUpdate` too.
A common misconception is that `getDerivedStateFromProps` and `componentWillReceiveProps` are only called when props "change". These lifecycles are called any time a parent component rerenders, regardless of whether the props are "different" from before. Because of this, it has always been unsafe to _unconditionally_ override state using either of these lifecycles. **Doing so will cause state updates to be lost.**
Let’s consider an example to demonstrate the problem. Here is a `EmailInput` component that "mirrors" an email prop in state:
At first, this component might look okay. State is initialized to the value specified by props and updated when we type into the `<input>`. But if our component's parent re-renders, anything we've typed into the `<input>` will be lost! ([See this demo for an example.](https://codesandbox.io/s/m3w9zn1z8x))
At first, this component might look okay. State is initialized to the value specified by props and updated when we type into the `<input>`. But if our component's parent rerenders, anything we've typed into the `<input>` will be lost! ([See this demo for an example.](https://codesandbox.io/s/m3w9zn1z8x)) This holds true even if we were to compare `nextProps.email !== this.state.email` before resetting.
We could use `shouldComponentUpdate` to ensure that our component did not re-render unless props changed. This would fix the simple component showed above. However in practice, components usually accept multiple props, and our component would re-render if any one of them changed— not just email.
Another thing to to keep in mind is that function and object props are often created inline and so will always bypass `shouldComponentUpdate`. For example, what if our component accepted a function to validate the current email address?
```js
<EmailInput
email={this.props.user.email}
validate={this.validateEmail.bind(this)}
/>
```
In this simple example, adding `shouldComponentUpdate` to rerender only when the email prop has changed could fix this. However in practice, components usually accept multiple props; another prop changing would still cause a rerender and improper reset. Function and object props are also often created inline, making it sometimes hard to implement a `shouldComponentUpdate` that reliably returns true only when a material change has happened. [Here is a demo that shows that happening.](https://codesandbox.io/s/jl0w6r9w59) As a result, `shouldComponentUpdate` is best used as a performance optimization, not to ensure correctness of derived state.
This example binds the validation callback inline and so it will pass a new function prop every time it renders— effectively bypassing `shouldComponentUpdate` entirely. ([Here is a demo that shows that happening.](https://codesandbox.io/s/jl0w6r9w59))
Hopefully it's clear by now why **it is a bad idea to unconditionally mirror props in state**. But what if we were to only update the state when the email prop changes? We'll take a look at that pattern next.
Hopefully it's clear by now why **it is a bad idea to unconditionally copy props to state**. Before reviewing possible solutions, let's look at a related problematic pattern: what if we were to only update the state when the email prop changes?
### Anti-pattern: Erasing state when props change
@ -116,36 +94,32 @@ class EmailInput extends Component {
>
> Even though the example above shows `componentWillReceiveProps`, the same anti-pattern applies to `getDerivedStateFromProps`.
We've just made a big improvement. Now our component will no longer erase what we've typed when it is re-rendered. At this point, what we have is fairly similar to the [scroll direction example](blog/2018/03/27/update-on-async-rendering.html#updating-state-based-on-props) we mentioned before.
There is still one subtle problem though, and it's probably easiest to illustrate with an example. Let's say our `EmailInput` component is used inside of an "edit profile" form. The first time the form is rendered, the component will display our email address. Let's say we edited the form (including our email address) but then changed our mind and clicked a "reset" button. At this point, we would expect all form fields to return to their initial values— but the `EmailInput` component **will not be reset**. Do you know why?
We've just made a big improvement. Now our component will erase what we've typed only when the props actually change.
The reason for this is that "committed" `props.email` never actually changed in the above scenario. (We never clicked "save".) So when the edit form re-rendered the input, it passed the same email address via props. ([See demo here.](https://codesandbox.io/s/mz5w04xpz9))
There is still a subtle problem. Imagine a password manager app using the above input component. When navigating between details for two accounts with the same email, the input would fail to reset. This is because the prop value passed to the component would be the same for both accounts! This would be a surprise to the user, as an unsaved change to one account would appear to affect other accounts that happened to share the same email. ([See demo here.](https://codesandbox.io/s/mz2lnkjkrx))
This problem could manifest itself even without a "reset" button. For example, imagine a password manager app using the above input component. When navigating between details for two accounts with the same email, the input would fail to reset. This is because the prop value passed to the component would be the same for both accounts! This would be a surprise to the user, as a draft change to one account would appear to affect other accounts that happened to share the same email. ([See demo here.](https://codesandbox.io/s/mz2lnkjkrx))
This design is fundamentally flawed, but it's also an easy mistake to make. ([I've made it myself!](https://twitter.com/brian_d_vaughn/status/959600888242307072)) Fortunately there are two alternatives that work better. The key to both is that **for any piece of data, you need to pick a single component that owns it as the source of truth, and avoid duplicating it in other components.** Let's take a look at each of the alternatives.
This design is fundamentally flawed, but it's also an easy mistake to make. [I've made it myself.](https://twitter.com/brian_d_vaughn/status/959600888242307072) Fortunately there are two alternatives that work better. The key to both is that **for any piece of data, you need to pick a single component that owns it as the source of truth, and avoid duplicating it in other components.** Let's take a look at each of the alternatives.
## Preferred Solutions
#### Alternative 1: Fully controlled component
### Recommendation: Fully controlled component
One way to avoid the problems mentioned above is to remove state from our component entirely. If the email address only exists as a prop, then we don't have to worry about conflicts with state. In this case, we could even convert `EmailInput` to a lighter-weight functional component:
One way to avoid the problems mentioned above is to remove state from our component entirely. If the email address only exists as a prop, then we don't have to worry about conflicts with state. We could even convert `EmailInput` to a lighter-weight functional component:
This approach simplifies the implementation of our component but it also has a potential downside: our component now requires more effort to use. For example, the parent form component will now also need to manage "draft" (unsaved) email state. ([Click here to see a demo of this pattern.](https://codesandbox.io/s/7154w1l551))
This approach simplifies the implementation of our component, but if we still want to store a draft value, the parent form component will now need to do that manually. ([Click here to see a demo of this pattern.](https://codesandbox.io/s/7154w1l551))
#### Alternative 2: Fully uncontrolled component
### Recommendation: Fully uncontrolled component with a `key`
Another alternative would be for our component to fully own the "draft" email state. This might be helpful if the "committed" state lives in a state container like Redux. In that case, our component could still accept a prop for the _initial_ value, but it would ignore any changes to that prop afterward. For example:
Another alternative would be for our component to fully own the "draft" email state. In that case, our component could still accept a prop for the _initial_ value, but it would ignore subsequent changes to that prop:
```js
class EmailInput extends Component {
state = {
email: this.props.defaultEmail
};
state = { email: this.props.defaultEmail };
handleChange = event => {
this.setState({ email: event.target.value });
@ -157,11 +131,7 @@ class EmailInput extends Component {
}
```
This design makes the component a little easier to use, but it also has a downside. Let's say that our "edit profile" form could be used to edit multiple users. Whenever a new user is selected, the form should reset the email field. If our `EmailInput` is uncontrolled, it will ignore any changes to `props.defaultEmail`. So how could we support this use case?
#### Option 1: Reset uncontrolled component with a `key`
One approach would be to use a special React attribute called `key`. React uses this property to decide whether to [_update_ a component instance or _create_ a new one](/docs/reconciliation.html#keys). In our case, we could use an attribute like a user id to recreate the email input any time a new user is selected. Each time the `EmailInput` is recreated, it will "reset" its state to the value specified by the `defaultEmail` prop.
In order to reset the value when moving to a different item (as in our password manager scenario), we can use the special React attribute called `key`. When a `key` changes, React will [_create_ a new component instance rather than _update_ the current one](/docs/reconciliation.html#keys). Keys are usually used for dynamic lists but are also useful here. In our case, we could use the user ID to recreate the email input any time a new user is selected:
```js
<EmailInput
@ -170,19 +140,17 @@ One approach would be to use a special React attribute called `key`. React uses
/>
```
([Click here to see a demo of this pattern.](https://codesandbox.io/s/6v1znlxyxn))
Each time the ID changes, the `EmailInput` will be recreated and its state will be reset to the latest `defaultEmail` value. ([Click here to see a demo of this pattern.](https://codesandbox.io/s/6v1znlxyxn)) With this approach, you don't have to add `key` to every input. It might make more sense to put a `key` on the whole form instead. Every time the key changes, all components within the form will be recreated with a freshly initialized state.
In most cases, this is the best way to handle state that needs to be reset.
> Note
>
> With this approach, you don't have to add `key` to every input. It might make more sense to put a `key` on the whole form instead. Every time the key changes, all components within the form will be re-created with a freshly initialized state.
>
> While this may sound slow, in practice the difference is often insignificant. It can even be faster if the components have heavy logic that runs on updates.
#### Option 2: Reset uncontrolled component with an id prop
> While this may sound slow, the performance difference is usually insignificant. Using a key can even be faster if the components have heavy logic that runs on updates since diffing gets bypassed for that subtree.
Recreating this simple example component is cheap, but what if the component was expensive to initialize? Or what if it had other state that we _did not want to reset_?
#### Alternative 1: Reset uncontrolled component with an ID prop
A slight variation on the above approach would be to watch for changes in a prop like "userID" and use it to reset state:
If `key` doesn't work for some reason (perhaps the component is very expensive to initialize), a workable but cumbersome solution would be to watch for changes to "userID" in getDerivedStateFromProps:
```js
class EmailInput extends Component {
@ -208,17 +176,15 @@ class EmailInput extends Component {
}
```
([Click here to see a demo of this pattern.](https://codesandbox.io/s/rjyvp7l3rq))
This also provides the flexibility to only reset parts of our component's internal state if we so choose. ([Click here to see a demo of this pattern.](https://codesandbox.io/s/rjyvp7l3rq))
> Note
>
> Even though the example above shows `getDerivedStateFromProps`, the same technique can be used with `componentWillReceiveProps`.
This approach can scale better with multiple state values, since fewer comparisons are required. It also provides the flexibility to only reset parts of our component's internal state.
#### Alternative 2: Reset uncontrolled component with an instance method
#### Option 3: Reset uncontrolled component with an instance method
Not every component accepts a special prop like "userID". (For example, what if we were writing a list component instead, and wanted to accept a scroll offset prop?) For cases like this, we could expose an instance method to imperatively reset the internal state:
More rarely, you may need to reset state even if there's no appropriate ID to use as `key`. One solution is to reset the key to a random value or autoincrementing number each time you want to reset. One other viable alternative is to exposing an instance method to imperatively reset the internal state:
```js
class EmailInput extends Component {
@ -236,69 +202,42 @@ class EmailInput extends Component {
The parent form component could then [use a `ref` to call this method](/docs/glossary.html#refs). ([Click here to see a demo of this pattern.](https://codesandbox.io/s/l70krvpykl))
> Note
>
> Refs can be useful when interfacing with imperative third party APIs or in certain, limited use cases like the one mentioned above, but generally we recommend you use them sparingly.
Refs can be useful in certain cases like this one, but generally we recommend you use them sparingly. Even in the demo, this imperative method is nonideal because two renders will occur instead of one.
-----
### Recap
To recap, when designing a component, it is important to decide whether its data will be controlled or uncontrolled.
Instead of trying to **"mirror" a prop value in state**, make the component **controlled**, and consolidate the two diverging values in the state of some parent component. For example, rather than accepting a "committed" `props.value` and tracking a "draft" `state.value`, a component could only display `props.value` and call `props.onChange` to notify the parent of a "draft" update. A form component above could then explicitly manage both values in its own state, (e.g.`state.draftValue` and `state.committedValue`), pass one of them down, and reset either of them when appropriate. (Don't forget you can use a nested object if the form contains multiple fields!)
Instead of trying to **"mirror" a prop value in state**, make the component **controlled**, and consolidate the two diverging values in the state of some parent component. For example, rather than a child accepting a "committed" `props.value` and tracking a "draft" `state.value`, have the parent manage both `state.draftValue` and `state.committedValue` and control the child's value directly. This makes the data flow more explicit and predictable.
For **uncontrolled** components, if you're trying to **"reset" one or more state fields** when a particular unrelated prop (usually an ID) changes, you have a few options:
1. To reset _all internal state_, use the `key` attribute.
2. To reset _some internal state_, watch for changes in a special property (e.g. `props.userID`).
3. Otherwise, consider falling back to an imperative instance method called with a `ref`.
For **uncontrolled** components, if you're trying to reset state when a particular prop (usually an ID) changes, you have a few options:
1. **To reset _all internal state_, use the `key` attribute (preferred).**
2. To reset _only certain state fields_, watch for changes in a special property (e.g. `props.userID`).
3. You can also consider fall back to an imperative instance method using refs.
## What about memoization?
We've also seen derived state used to ensure an expensive value is recomputed only when the inputs change. This technique is known as [memoization](https://en.wikipedia.org/wiki/Memoization).
Using derived state for memoization isn't necessarily bad, but there are reasons you may want to avoid it. The above examples illustrate that there is a certain amount of complexity inherent in managing derived state. This complexity increases with each derived property. For example, if we add a second derived field to our component state then our implementation would need to separately track changes to both. For `getDerivedStateFromProps`, this might look like:
```js
class Example extends Component {
state = {};
static getDerivedStateFromProps(props, state) {
const updatedState = {};
if (props.bar !== state.prevBarFromProps) {
updatedState.prevBarFromProps = props.bar;
updatedState.derivedBar = deriveBar(props.bar);
}
if (props.foo !== state.prevFooFromProps) {
updatedState.prevFooFromProps = props.foo;
updatedState.derivedFoo = deriveFoo(props.foo);
}
// Other derived fields would go here...
return updatedState;
}
We've also seen derived state used to ensure an expensive value used in `render` is recomputed only when the inputs change. This technique is known as [memoization](https://en.wikipedia.org/wiki/Memoization).
// ...
}
```
Using derived state for memoization isn't necessarily bad, but it's usually not the best solution. There is inherent complexity in managing derived state, and this complexity increases with each additional property. For example, if we add a second derived field to our component state then our implementation would need to separately track changes to both.
Although the above pattern _works_, it isn't what either `componentWillReceiveProps` or `getDerivedStateFromProps` were meant to be used for. This component isn't reacting to **changes in props**. It's just computing values based on the **current props**, and there is a simpler way to do this that doesn't even require state.
Let's look at another example to illustrate this. Here is a component that accepts an array of items as `props.list` and allows a user to filter the array by entering text. We could use derived state to store the filtered list:
Let's look at an example of one component that takes one prop—a list of items—and renders the items that match a search query entered by the user. We could use derived state to store the filtered list:
```js
class Example extends Component {
state = {
filterText: "",
prevFilterText: ""
};
static getDerivedStateFromProps(props, state) {
// Re-run the filter whenever the list array or filter text change:
// Re-run the filter whenever the list array or filter text change.
// Note we need to store prevPropsList and prevFilterText to detect changes.
if (
props.list !== state.prevPropsList ||
state.prevFilterText !== state.filterText
) {
// Note that to do this, state needs to explicitly track both:
// prevPropsList - so we can detect a change in props.list
// prevFilterText - so we can detect a change in state.filterText
return {
prevPropsList: props.list,
prevFilterText: state.filterText,
@ -323,10 +262,10 @@ class Example extends Component {
}
```
This implementation is more complicated than it needs to be, because it has to separately track and detect changes in both props and state in order to properly update the filtered list. In this example, we could simplify things by using `PureComponent` and moving the filter operation into the render method:
This implementation avoids recalculating `filteredList` more often than necessary. But it is more complicated than it needs to be, because it has to separately track and detect changes in both props and state in order to properly update the filtered list. In this example, we could simplify things by using `PureComponent` and moving the filter operation into the render method:
```js
// PureComponents only re-render if at least one state or prop value changes.
// PureComponents only rerender if at least one state or prop value changes.
// Change is determined by doing a shallow comparison of state and prop keys.
class Example extends PureComponent {
// State only needs to hold the current filter text value:
@ -339,8 +278,8 @@ class Example extends PureComponent {
};
render() {
// The render method on this PureComponent is not called unless either
// props.list or state.filterText have referentially different values.
// The render method on this PureComponent is called only if
// props.list or state.filterText has changed.
const filteredList = this.props.list.filter(
item => item.text.includes(this.state.filterText)
)
@ -355,22 +294,18 @@ class Example extends PureComponent {
}
```
The above approach is much cleaner and simpler than the derived state version, but it has some limitations. Filtering may be slow for large lists, and `PureComponent` won't prevent re-renders if props other than `list` change. To address both of these concerns, we could add a memoization helper to avoid unnecessarily re-filtering our list:
The above approach is much cleaner and simpler than the derived state version. Occasionally, this won't be good enough—filtering may be slow for large lists, and `PureComponent` won't prevent rerenders if another prop were to change. To address both of these concerns, we could add a memoization helper to avoid unnecessarily re-filtering our list:
```js
import memoize from "memoize-one";
class Example extends Component {
// State only needs to hold the current filter text value:
state = {
filterText: ""
};
state = { filterText: "" };
// Re-run the filter whenever the list array or filter text change:
// Re-run the filter whenever the list array or filter text changes:
@ -395,16 +329,14 @@ class Example extends Component {
This is much simpler and performs just as well as the derived state version!
There are a couple of constraints to consider when using memoization though:
When using memoization, remember a couple of constraints:
1. In most cases, you'll want to **attach the memoized function to a component instance**. This prevents multiple instances of a component from resetting each other's memoized keys.
1. Typically you'll want to use a memoization helper with a **limited cache size** in order to prevent memory from "leaking" over time. (In the example above, we used `memoize-one` because it only caches the most recent argument and result.)
1. Memoization will not work properly if `props.items` is recreated each time the parent component renders. Hopefully, this should not be the case for large arrays. If it were, you'd want to address that problem first! (This limitation also applies to the derived state versions above.)
1. Typically you'll want to use a memoization helper with a **limited cache size** in order to prevent memory leaks over time. (In the example above, we used `memoize-one` because it only caches the most recent argument and result.)
1. None of the implementations shown in this section will work if `props.items` is recreated each time the parent component renders. But in most cases, this setup is appropriate.
## In closing
The examples above are intentionally simplified in order to highlight specific coding patterns. In real world applications, components often contain a mix of controlled and uncontrolled behaviors. This is okay! Just be careful to ensure that each behavior has a clear source of truth in order to avoid the anti-patterns mentioned above.
It is also worth re-iterating that `getDerivedStateFromProps` (and derived state in general) should be used sparingly because of the inherent complexity involved.
In real world applications, components often contain a mix of controlled and uncontrolled behaviors. This is okay! If each value has a clear source of truth, you can avoid the anti-patterns mentioned above.
If you have a use case that you think falls outside of these patterns, please share it with us on [GitHub](https://github.com/reactjs/reactjs.org/issues/new) or Twitter!
It is also worth re-iterating that `getDerivedStateFromProps` (and derived state in general) is an advanced feature and should be used sparingly because of this complexity. If your use case falls outside of these patterns, please share it with us on [GitHub](https://github.com/reactjs/reactjs.org/issues/new) or Twitter!