Skip to content

AppBarButton's aren't correctly re-rendered when the underlying CommandBar isn't rerendered #111

Description

@dstaley

When React attempts to update the AppBarButton's of a CommandBar when the underlying CommandBar isn't marked for changes, the buttons aren't rerendered, becoming out-of-sync with the React VDOM.

image

(One interesting note from this screenshot: the AppBarButtons are missing children elements after React tries to update them. Normally, they'd have a Root Grid containing a Border and Grid element, the latter of which contains a Viewbox and TextBlock.)

In this example, the <Actions /> component pulls data from a Context provider to determine what AppBarButtons to render. Since CommandBar isn't listening to that context, it doesn't need to rerender on context changes, but <Actions /> does.

import React, {useContext} from 'react';
import {
  CommandBar as XAMLCommandBar,
  CommandBarDefaultLabelPosition,
  VerticalAlignment,
  StackPanel,
  Orientation,
  Button,
  FontIcon,
  TextBlock,
  TextLineBounds,
  AppBarButton,
} from 'react-native-xaml';
import {RouterContext} from './router';
import {ToolbarContext} from './Toolbar';

const BackButton = () => {
  const {canGoBack, goBack} = useContext(RouterContext);
  return (
    <Button
      resources={{
        ButtonBackground: 'Transparent',
        ButtonBackgroundDisabled: 'Transparent',
        ButtonBorderBrushDisabled: 'Transparent',
      }}
      borderBrush="transparent"
      isEnabled={canGoBack}
      onClick={goBack}>
      <FontIcon
        fontFamily="Segoe Fluent Icons"
        glyph="&#xE72B;"
        fontSize={16}
      />
    </Button>
  );
};

const Title = () => {
  const {title} = useContext(ToolbarContext);
  return (
    <TextBlock
      verticalAlignment={VerticalAlignment.Center}
      text={title}
      fontSize={20}
      fontWeight={700}
      textLineBounds={TextLineBounds.Tight}
    />
  );
};

const Actions = () => {
  const {actions} = useContext(ToolbarContext);
  return (
    <>
      {actions.map(action => (
        <AppBarButton
          key={action.title}
          label={action.title}
          onClick={action.onClick}
          isEnabled={!action.disabled}>
          <FontIcon fontFamily="Segoe Fluent Icons" glyph={action.icon} />
        </AppBarButton>
      ))}
    </>
  );
};

export const CommandBar = () => {
  return (
    <XAMLCommandBar
      isOpen={false}
      defaultLabelPosition={CommandBarDefaultLabelPosition.Right}
      verticalContentAlignment={VerticalAlignment.Center}>
      <StackPanel
        orientation={Orientation.Horizontal}
        verticalAlignment={VerticalAlignment.Center}>
        <BackButton />
        <Title />
      </StackPanel>
      <Actions />
    </XAMLCommandBar>
  );
};

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions