LoginSignup
0
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-03-13

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を分けて制作してみました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0