widgetti / ipyreact

React for ipywidgets that just works. No webpack, no npm, no hassle
BSD 3-Clause "New" or "Revised" License
104 stars 8 forks source link

MaterialUI Snackbar not working in Ipyreact #45

Closed seidlr closed 4 months ago

seidlr commented 8 months ago

I've tried to create a simple snackbar component using materialui and ipyreact. When run in the playground on esm it works.

When run in a notebook it seems to not be able to load react.

%%react 

import * as React from "react";
import {Button, Snackbar, IconButton}  from "https://esm.sh/@mui/material";
import {CloseIcon} from "https://esm.sh/@mui/icons-material";

export default function SimpleSnackbar() {
  const [open, setOpen] = React.useState(false);

  const handleClick = () => {
    setOpen(true);
  };

  const handleClose = (event: React.SyntheticEvent | Event, reason?: string) => {
    if (reason === 'clickaway') {
      return;
    }

    setOpen(false);
  };

  const action = (
    <React.Fragment>
      <Button color="secondary" size="small" onClick={handleClose}>
        UNDO
      </Button>
      <IconButton
        size="small"
        aria-label="close"
        color="inherit"
        onClick={handleClose}
      >
        <Close fontSize="small" />
      </IconButton>
    </React.Fragment>
  );

  return (
    <div>
      <Button onClick={handleClick}>Open simple snackbar</Button>
      <Snackbar
        open={open}
        autoHideDuration={6000}
        onClose={handleClose}
        message="Note archived"
        action={action}
      />
    </div>
  );
}

Error:

Uncaught (in promise) Error: Unable to resolve specifier 'react/jsx-runtime?external=react,react-dom'

Any idea what is happening here?

kolibril13 commented 8 months ago

I've run into this issue before https://github.com/widgetti/ipyreact/issues/2 and this is hard to debug in ipyreact. I suggest you use anywidget instead, which also has support for react components, and it's also easier to install your react components via npm.

Just made a minimal example for your snackbar with anywidget:

https://github.com/Octoframes/anywidget-materialui

https://github.com/widgetti/ipyreact/assets/44469195/aee60f01-5de7-4fef-b171-0a4e47856765

maartenbreddels commented 4 months ago

Hi Robert,

ipyreact 0.4.0 has improved several things and it can work now. Note that your example does not work (Close is undefined), but I took @kolibril13 's js code as an inspiration.

import ipyreact
ipyreact.define_import_map({
    "@mui/material": "https://esm.sh/@mui/material@5.11.10?external=react,react-dom",
    "@mui/icons-material/": "https://esm.sh/@mui/icons-material/?external=react,react-dom",
})
%load_ext ipyreact
%%react 
import * as React from 'react';
import Button from '@mui/material/Button';
import Snackbar from '@mui/material/Snackbar';
import IconButton from '@mui/material/IconButton';

export default () => {
  const [open, setOpen] = React.useState(false);

  const handleClick = () => {
    setOpen(true);
  };

  const handleClose = (event, reason) => {
    if (reason === 'clickaway') {
      return;
    }

    setOpen(false);
  };

  const action = (
    <React.Fragment>
      <Button color="secondary" size="small" onClick={handleClose}>
        UNDO
      </Button>
      <IconButton
        size="small"
        aria-label="close"
        color="inherit"
        onClick={handleClose}
      >
      </IconButton>
    </React.Fragment>
  );

  return (
    <div>
      <Button onClick={handleClick}>Open simple snackbar</Button>
      <Snackbar
        open={open}
        autoHideDuration={6000}
        onClose={handleClose}
        message="Note archived"
        action={action}
      />
    </div>
  );
};

See https://github.com/widgetti/ipyreact?tab=readme-ov-file#why-does-ipyreact-provides-react for why you would use ipyreact vs anywidget.

Also, if you do not want to use esm.sh and provide a bundle (similar to @kolibril13 's example), see https://github.com/widgetti/ipyreact?tab=readme-ov-file#bundled-esm-modules