如何解决来自notistack 的React Snackbar Compnent 无法在其GUI 中处理长文本,因为在小窗口大小的情况下文本会消失
我是 React UI 库(如 material-ui 和 notstack)的新手。在我的项目中,像组件一样与一些样式/css 一起使用。在整个 React 应用程序中,当在这个 Snackbar 组件中放入一个长动态文本时,它的 GUI 会受到干扰,并且文本会被切断并离开组件。我如何才能解决这个问题并使其具有响应性,以便它可以处理其中的很长的文本。
以下是文件 SanckbarProvider.tsx 中 Snackbar 组件的代码
import React from "react";
import {
SnackbarProvider as NisSnackbarProvider,SnackbarProviderProps,} from "notistack";
import { Fade } from "@material-ui/core";
import { TransitionProps } from "@material-ui/core/transitions";
import { makeStyles } from "@material-ui/core/styles";
import { CloseButton } from "./CloseButton";
const variantStyle = (color: string,backgroundColor: string) => ({
height: "36px;",color: `${color} !important`,backgroundColor: `${backgroundColor} !important`,opacity: "0.95 !important",borderRadius: "3px;",boxShadow: "0 2px 10px 0 rgba(0,0.1);",alignContent: "center",marginRight: "-4px !important",});
const useStyles = makeStyles(() => ({
success: variantStyle("#3AA658","#BBE9B6"),error: variantStyle("#FFFFFF","#D07B7B"),warning: variantStyle("#FFFFFF","#EC9E4D"),info: variantStyle("#FFFFFF","#6da4d0"),}));
const FadeTransition = (props: TransitionProps) => <Fade {...props}/>;
const SnackbarProvider = ({ children }: SnackbarProviderProps): JSX.Element => {
const classes = useStyles();
return (
<NisSnackbarProvider
classes={{
variantSuccess: classes.success,variantError: classes.error,variantWarning: classes.warning,variantInfo: classes.info,}}
action={key => <CloseButton id={key} />}
maxSnack={7}
anchorOrigin={{vertical: "bottom",horizontal: "right"}}
autoHideDuration={3000}
transitionDuration={{enter: 1000,exit: 500}}
TransitionComponent={FadeTransition}
variant={"success"}
preventDuplicate
>
{children}
</NisSnackbarProvider>
);
};
export default SnackbarProvider;
这是 App.tsx 中的主要应用组件
const ContentWrapper = styled.div<WrapperProps>`
overflow-x: hidden;
background: ${(props) => (props.showBackground ? "white" : "transparent")};
height: calc(100vh);
`;
const LinearProgressWrapper = styled.div`
position: absolute;
top: ${LINEAR_PROGRESS_TOP_POSITION};
left: 0;
width: 100%;
z-index: 100;
`;
const LinearProgressStyled = styled(LinearProgress)`
height: 6px;
`;
const App = (): JSX.Element => {
const dispatch = useDispatch();
const size = useScreenSize();
const loginState = useSelector(loginSelector);
const showLoadingIndicator = useSelector(pendingApiCallsExist);
const { authenticated } = loginState;
const selectedScreen = useSelector((state: IRootState) => state.ui.view);
const shouldShowBigTopbar = !!(selectedScreen === ViewTypes.WorkspacesList && IS_MAC_OS);
// for some reasons,after logout,sizesReducer is reset.
// So it's needed to manually trigger recalculation
useLayoutEffect(() => {
if (size.height !== -1) {
dispatch(resizeAction(size));
}
},[authenticated,dispatch,size]);
return (
<StylesProvider injectFirst>
<MuiThemeProvider theme={maTheme}>
<ThemeProvider theme={maTheme}>
<I18nextProvider i18n={i18n}>
<SnackbarProvider>
<Socket url={SOCKET_URL}/>
<ContentWrapper
showBackground={shouldShowBigTopbar}
>
<Router history={routerHistory}>
<Routes />
{showLoadingIndicator && <LinearProgressWrapper>
<LinearProgressStyled />
</LinearProgressWrapper>}
<SnackbarsList />
</Router>
</ContentWrapper>
</SnackbarProvider>
</I18nextProvider>
</ThemeProvider>
</MuiThemeProvider>
</StylesProvider>
);
};
export default App;
这是用于呈现信息和更多信息小吃栏的代码
import React,{ useState } from "react";
import {
Card,CardActions,Collapse,IconButton,Paper,Typography,} from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import CloseIcon from "@material-ui/icons/Close";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import { SnackbarMessage,useSnackbar } from "notistack";
import { autoUpdater } from "electron-updater";
const infoBase = {
alignContent: "center",backgroundColor: "#D07B7B",color: "#FFFFFF",marginRight: "-4px",opacity: "0.95",padding: "6px 16px",};
const useStyles = makeStyles((theme) => ({
card: {
marginRight: "-4px",maxWidth: 440,minWidth: 344,},info: {
...infoBase,height: "36px",icons: {
marginLeft: "auto !important",marginRight: "-8px",paddingLeft: "16px",expand: {
color: "#FFFFFF",padding: "8px 8px",transform: "rotate(0deg)",transition: theme.transitions.create("transform",{
duration: theme.transitions.duration.shortest,}),expandOpen: {
transform: "rotate(180deg)",moreInfo: {
...infoBase,maxHeight: "156px",overflowWrap: "break-word",}));
interface IProps {
id: string | number,info: string,moreInfo: string,}
const MoreInfoSnackbar = (props: IProps): JSX.Element => {
const {id,info,moreInfo} = props;
const classes = useStyles();
const { closeSnackbar } = useSnackbar();
const [expanded,setExpanded] = useState(false);
const handleExpandClick = () => setExpanded(!expanded);
const handleDismiss = () => closeSnackbar(id);
// TODO: What the heck to do with this? - very,very hacky!
const renderErrorIcon = () => (
<svg className="MuiSvgIcon-root" focusable="false" viewBox="0 0 28 28"
aria-hidden="true"
style={{fontSize: "20px",marginInlineEnd: "8px"}}
>
<path
d="M12,2C17.53,2 22,6.47 22,12C22,17.53 17.53,22 12,22C6.47,22 2,17.53 2,12C2,6.47 6.47,2 12,2M15.59,7L12,10.59L8.41,7L7,8.41L10.59,12L7,15.59L8.41,17L12,13.41L15.59,17L17,15.59L13.41,12L17,8.41L15.59,7Z">
</path>
</svg>
);
const renderActionIcons = () => (
<div className={classes.icons}>
<IconButton
style={{
transform: expanded ? "rotate(180deg)" : "",}}
aria-label="Show more"
className={classes.expand}
onClick={handleExpandClick}
>
<ExpandMoreIcon />
</IconButton>
<IconButton className={classes.expand} onClick={handleDismiss}>
<CloseIcon />
</IconButton>
</div>
);
const renderInfo = () => (
<CardActions className={classes.info}>
{renderErrorIcon()}
<Typography gutterBottom>
{info}
</Typography>
{renderActionIcons()}
</CardActions>
);
const renderMoreInfo = () => (
<Collapse in={expanded} timeout="auto" unmountOnExit>
<Paper className={classes.moreInfo}>
<Typography gutterBottom>
{moreInfo}
</Typography>
</Paper>
</Collapse>
);
return (
<Card className={classes.card}>
{renderInfo()}
{renderMoreInfo()}
</Card>
);
};
type IErrors = {
info: string
moreInfo: string
}
const processMessage = (message: React.ReactNode): IErrors => {
if (typeof message === "string") {
return {info: message,moreInfo: ""};
}
if (Array.isArray(message)) {
const info = typeof message[0] === "string" ? message[0] : "";
const moreInfo = typeof message[1] === "string" ? message[1] : "";
return {info,moreInfo};
}
return {info: "",moreInfo: ""};
};
/**
This is the set callback signature that notistack allows for returning
a customized snackbar.
It is not straightforward to get more data into the custom snackbar.
So we leverage the message param. It can be a string or an array.
We could use a JSON string and then parse it to get a bunch more options
but for now,we are just adding an extra "moreInfo" string
Works with a message array of [message,moreInfo],I.e:
import { getMoreInfoSnackbar } from "../../snacks/MoreInfoSnackbar";
...
enqueueSnackbar(
["something went wrong","More detailed info,accessed via dropdown"],{
content: getMoreInfoSnackbar,persist: true,);
*/
export const getMoreInfoSnackbar = (key: React.ReactText,message: React.ReactNode): SnackbarMessage => {
const {info,moreInfo} = processMessage(message);
return <MoreInfoSnackbar id={key} info={info} moreInfo={moreInfo}/>;
};
export default MoreInfoSnackbar;
有人可以帮助解决上述问题吗?如何让这个零食栏组件随着其中的内容调整大小/增长,并调整和对齐内容以适应它。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。