usePreviousValue
Returns the value this hook held on the previous distinct value, or null on the first build. It tracks the last value that differed from the current one, so it is the safe way to ask "what was this before it changed?".
This page lives at /use_previous - the URL reflects the older usePrevious hook (now deprecated, covered below). The current hook is usePreviousValue.
class PageIndicator extends HookWidget {
final int currentPage;
const PageIndicator({super.key, required this.currentPage});
Widget build(BuildContext context) {
final previousPage = usePreviousValue(currentPage); // <- null on the first build
// Compare the previous value against the current one to derive direction.
final isForward = previousPage != null && currentPage > previousPage;
return Icon(isForward ? Icons.arrow_forward : Icons.arrow_back);
}
}
Signature
T? usePreviousValue<T>(T value, {HookKeys keys = hookKeysEmpty});
The return type is nullable: there is no previous value on the first build. Internally it keeps two cells - the current value and the previous one - and only shifts them when the incoming value differs (by ==) from the stored current. Passing keys resets both cells when the keys change.
Use cases
- Deriving something from a transition rather than a single value, e.g. computing scroll or page direction by comparing the new value against the old one.
- Detecting that a specific value changed without an effect, when you only need the old value during build.
Caveats
-
Equal values (by
==) do not advance the previous value. If the same value arrives twice in a row,usePreviousValuekeeps reporting the last value that was actually different - it does not return "the value from the previous build". -
The previous value is only meaningful during build. For reacting to a change with a side effect (analytics, navigation, a controller call), use
useEffectwith the value in its keys instead - the effect's body sees the new value and runs only on change.
usePrevious
("This hook is unsafe as it depends on the rebuild frequency. Use usePreviousValue or useEffect instead")
T? usePrevious<T>(T value, {HookKeys keys = hookKeysEmpty});
The original variant. It returns the value from the previous build, regardless of whether it changed.
usePrevious is deprecated. It captures whatever was passed on the last build, so its result depends on how often the widget happens to rebuild - an unrelated rebuild advances the "previous" value and the change you wanted to observe is lost. Use usePreviousValue when you need the last distinct value, or useEffect when you need to act on a change.
See also
- useValueChanged - run a computation when a value changes, with both the old and new value
- useEffect - the right tool for side effects on change
- usePreviousIfNull - keep the last non-null value across transient
nulls