Help us understand the problem. What is going on with this article?

ReactでDrawerをイベント処理と表示のcomponentを分けて制作

Drawerを作るときに考えられる要素としては下記になります。

  • Drawerを開くときのボタン
  • Drawerを閉じるときのDrawerの中のボタン
  • Drawerの中身
  • containerの上に重なるalphaかかったが黒レイヤー

この要素のなかで、Drawerが開いているかどうかを判定する処理と開閉する際のイベント処理をするComponentと、Drawerの中身をただ愚直に書くだけのcomponentとを分けたいと思います。そのほうがコードの見通しがよくなると思うので。

書いてみた

  • Material-uiを使用

Sanple.tsx(Drawerトリガーのボタン)

  • Drawerを開く処理を行うボタンを配置
  • reducerを通してDrawerを開く
Sample.tsx
<Button
  variant="contained"
  color="primary"
  type="button"
  onClick={sideMenu(true)}>
  Drawer
</Button>
<DrawerWrapper component={<Drawer />} />

イベント処理をするComponent

  • propsのcomponentはDrawerの中身をただ愚直に書くだけのcomponent。そのcomponentにReact.cloneElementでDrawerを閉じるevent処理と開閉判定のbooleanをpropsとして渡しています
  • 開閉判定はreducerから取得しています
DrawerWrapper.tsx
export interface ImplProps {
  closeSideMenu?: () => void;
  isSideMenu?: boolean;
}

interface ImplInnerProps {
  sideMenuAction: (arg1: boolean) => void;
  isSideMenu: boolean;
}

interface ImplOuterProps {
  component: ReactElement;
}

export type TypeDrawerWrapper = ImplInnerProps & ImplOuterProps;

const DrawerWrapper: FC<TypeDrawerWrapper> = props => {
  const { component, isSideMenu, sideMenuAction } = props;
  const closeSideMenu = useCallback(() => {
    sideMenuAction(false);
  }, [sideMenuAction]);
  return React.cloneElement(component, { isSideMenu, closeSideMenu });
};

const mapStateToProps = (state: ImplState) => ({
  isSideMenu: state.animatio.isSideMenu
});

const enhance = compose<TypeDrawerWrapper, ImplOuterProps>(
  connect(mapStateToProps, {
    sideMenuAction,
  })
);

const Drawer = enhance(DrawerWrapper);
export default Drawer;

composeの型定義は下記

compose<propsで設定したcomponentのprops, このcomponent自体のprops>

中身をコーディングするComponent

  • propsはDrawerWrapper.tsxのReact.cloneElementで設定したpropsです
  • その取得したpropsを元に表示画面を制作してます
  • 背景をClickするとDrawerが閉じます
  • CloseボタンをClickするとDrawerが閉じます
Drawer.tsx
const Drawer: FC<ImplProps> = props => {
  const { isSideMenu, closeSideMenu } = props;
  return (
    <div>
      <DrawerBg onClick={closeSideMenu} isSideMenu={isSideMenu} />
      <DrawerInner isSideMenu={isSideMenu}>
        <Button
          variant="outlined"
          color="secondary"
          type="button"
          onClick={closeSideMenu}>
          Close
        </Button>
        <ul>
          <li></li>
          <li></li>
          <li></li>
        </ul>
      </DrawerInner>
    </div>
  );
};

export default Drawer;

以上になります。
event処理とReducerからstateを取得する処理のcomponentと、画面表示だけのcomponentを分けて制作してみました。

macotok
React好き
access
SDNからセンサ、家電、電子書籍まで。ACCESSはあらゆるレイヤのデバイス、サービスを「繋げて」いきます。
http://jp.access-company.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away