lazyData<T> method

ValueWrapper<T> lazyData<T>(
  1. T init()
)

Keeps track of some data that can be stateful. You may set the value of returned ValueWrapper both:

  1. Outside of the build, like a normal call to setState
  2. Inside of the build, to use its value inside build

This is a more powerful alternative to lazyState.

Implementation

ValueWrapper<T> lazyData<T>(T Function() init) {
  // Create a place to store the data, which should be lazily initialized
  final dataWrapper = use.callonce(() => _LazyMutable(init));

  // Create a getter on first build, but allow it to be changed
  final getterWrapper = use.callonce(() {
    return _Mutable(() => dataWrapper.value);
  });

  // Keep the same setter between builds to prevent unnecessary rebuilds
  final setter = use.register((api) {
    return (T newState) {
      api.rebuild((_) => dataWrapper.value = newState);
    };
  });

  // If the data has changed, then we need to recreate the getter
  // NOTE: https://github.com/GregoryConrad/rearch-dart/issues/277
  final lastSeenDataWrapper = use.callonce(() {
    // NOTE: We want to compare against something that definitely isn't equal
    // the first time the state has been mutated.
    // Thus, we use a private const object (const _Nothing()),
    // since that is guaranteed to be equal to nothing else.
    return _Mutable<Object?>(const _Nothing());
  });
  final hasDataChanged = dataWrapper.hasBeenMutated &&
      dataWrapper.value != lastSeenDataWrapper.value;
  if (hasDataChanged) {
    getterWrapper.value = () => dataWrapper.value;
    lastSeenDataWrapper.value = dataWrapper.value;
  }

  return (getterWrapper.value, setter);
}