Repository: flutter/flutter
File: packages/flutter/lib/src/material/tabs.dart (Dart)

Code before:
        // The scrolling tabs should not show an overscroll indicator.
        behavior: ScrollConfiguration.of(context).copyWith(overscroll: false),
        child: SingleChildScrollView(
          dragStartBehavior: widget.dragStartBehavior,
          scrollDirection: Axis.horizontal,
          controller: _effectiveScrollController,
          padding: effectivePadding,
          physics: widget.physics,
          child: tabBar,
        ),
      );
      if (theme.useMaterial3) {
        final AlignmentGeometry effectiveAlignment = switch (effectiveTabAlignment) {
          TabAlignment.center => Alignment.center,
          TabAlignment.start ||
          TabAlignment.startOffset ||
          TabAlignment.fill => AlignmentDirectional.centerStart,
        };

        final Color dividerColor =
            widget.dividerColor ?? tabBarTheme.dividerColor ?? _defaults.dividerColor!;
        final double dividerHeight =
            widget.dividerHeight ?? tabBarTheme.dividerHeight ?? _defaults.dividerHeight!;

        tabBar = Align(
          heightFactor: 1.0,
          widthFactor: dividerHeight > 0 ? null : 1.0,
          alignment: effectiveAlignment,
          child: tabBar,
        );

        if (dividerColor != Colors.transparent && dividerHeight > 0) {
          tabBar = CustomPaint(
            painter: _DividerPainter(dividerColor: dividerColor, dividerHeight: dividerHeight),
            child: tabBar,
          );
        }
      }
    } else if (widget.padding != null) {
      tabBar = Padding(padding: widget.padding!, child: tabBar);
    }

    return Material(
      type: MaterialType.transparency,
      child: MediaQuery(
        data: MediaQuery.of(
          context,
        ).copyWith(textScaler: widget.textScaler ?? tabBarTheme.textScaler),
        child: tabBar,
      ),
    );

Review comment (refactor):
Both the old and new code path attach here, in build(), which feels very side-effect-y. Should we move this to `didChangeDependencies()` ?

Code after:

      final WidgetStateProperty<Color?> defaultOverlay = WidgetStateProperty.resolveWith<Color?>((
        Set<WidgetState> states,
      ) {
        final Set<WidgetState> effectiveStates = selectedState.toSet()..addAll(states);
        return _defaults.overlayColor?.resolve(effectiveStates);
      });
      wrappedTabs[index] = InkWell(
        mouseCursor: effectiveMouseCursor,
        onTap: () {
          _handleTap(index);
        },
        onHover: (bool value) {
          widget.onHover?.call(value, index);
        },
        onFocusChange: (bool value) {
          widget.onFocusChange?.call(value, index);
        },
        enableFeedback: widget.enableFeedback ?? true,
        overlayColor: widget.overlayColor ?? tabBarTheme.overlayColor ?? defaultOverlay,
        splashFactory: widget.splashFactory ?? tabBarTheme.splashFactory ?? _defaults.splashFactory,
        borderRadius:
            widget.splashBorderRadius ??
            tabBarTheme.splashBorderRadius ??
            _defaults.splashBorderRadius,
        child: Padding(
          padding: EdgeInsets.only(bottom: widget.indicatorWeight),
          child: Semantics(
            // This has to be wrapped above the Stack to override any role set by the child.
            role: SemanticsRole.tab,
            child: Stack(
              children: <Widget>[
                wrappedTabs[index],
                Semantics(
                  selected: index == _currentIndex,
                  label: kIsWeb
                      ? null
                      : localizations.tabLabel(tabIndex: index + 1, tabCount: tabCount),
                ),
              ],
            ),
          ),
        ),
      );
      wrappedTabs[index] = MergeSemantics(child: wrappedTabs[index]);
      if (!widget.isScrollable && effectiveTabAlignment == TabAlignment.fill) {
        wrappedTabs[index] = Expanded(child: wrappedTabs[index]);
      }
    }

    Widget tabBar = Semantics(