reactjs 在自定义钩子中呈现我的react组件

s4n0splo  于 2023-04-11  发布在  React
关注(0)|答案(1)|浏览(163)

我使用的是React 18MUI version 5nanostores version 0.7.4。我写了一个名为useApi.tsx的钩子,每当我使用这个钩子时,它都会为我初始化一个新的axios示例。现在在这个钩子中,我定义了一个拦截器来监听错误。它工作得很好,不管是什么错误,它都会调用responseErrorHandler方法。代码如下:

import axios from 'axios';
import { Notification } from '../components/Notification/Notification.component';

export function useApi() {
    const api = axios.create({
        baseURL: import.meta.env.VITE_BACKEND_URL,
    });

    api.interceptors.response.use(null, responseErrorHandler);

    return { api };
}

function responseErrorHandler(error) {
    <Notification
        color="error"
        text="Something went wrong, please try again ..."
    />;

    return Promise.reject(error);
}

下面是Notification组件代码:

import {
    Alert,
    AlertColor,
    Snackbar,
    SnackbarCloseReason,
} from '@mui/material';
import { useStore } from '@nanostores/react';
import { useEffect } from 'react';
import { NotificationStateStore } from './Notification.store';

export function Notification({
    text,
    color,
    autoHideDuration = 6000,
}: {
    text: string;
    color: AlertColor;
    autoHideDuration?: number;
}) {
    const { actions, states } = NotificationStateStore;
    const notificationState = useStore(states.notificationState);
    const handleClose = (
        event: Event | React.SyntheticEvent<any, Event>,
        reason?: SnackbarCloseReason,
    ) => {
        if (reason === 'clickaway') {
            return;
        }
        actions.closeNotification();
    };

    useEffect(() => {
        actions.showNotification();
    }, []);

    return (
        <Snackbar
            open={notificationState}
            autoHideDuration={autoHideDuration}
            onClose={handleClose}
        >
            <Alert
                onClose={handleClose}
                severity={color}
                sx={{ width: '100%' }}
            >
                {text}
            </Alert>
        </Snackbar>
    );
}

正如你所看到的,我调用了actions.showNotification();来向用户显示通知,下面是Notification.store.ts内部的代码:

import { action, atom } from 'nanostores';

const notification = atom<boolean | undefined>();
const showNotification = action(
    notification,
    'showNotification',
    (state) => {
        state.set(true);
    },
);
const closeNotification = action(
    notification,
    'closeNotification',
    (state) => {
        state.set(false);
    },
);

export const NotificationStateStore = {
    states: { notificationState: notification },
    actions: { showNotification, closeNotification },
};

我的问题是它不起作用,我的意思是它不会在前端显示通知。这里你可以看到我在github中的代码:https://github.com/kasir-barati/open-ai-summaries/tree/d717f7e64d9e529f6d6c2aa698b464814512b29e

63lcw9qa

63lcw9qa1#

你试图在一个普通的JavaScript函数(responseErrorHandler)中呈现一个React组件,甚至没有返回它。你可以在responseErrorHandler之外管理通知的状态,并在组件中使用它。
NotificationStateStore存储通知文本和颜色:

import { AlertColor } from '@mui/material';
import { action, atom } from 'nanostores';

type NotificationState = {
    open: boolean;
    text: string;
    color: AlertColor;
    autoHideDuration?: number;
};
export type Notification = Omit<NotificationState, 'open'>;

const notification = atom<NotificationState>();
const showNotification = action(
    notification,
    'showNotification',
    (state, notification: Notification) => {
        const { autoHideDuration = 6000, ...rest } = notification;
        state.set({ ...rest, autoHideDuration, open: true });
    },
);
const closeNotification = action(
    notification,
    'closeNotification',
    (state) => {
        state.set(undefined);
    },
);

export const NotificationStateStore = {
    states: { notification },
    actions: { showNotification, closeNotification },
};

responseErrorHandler使用showNotification操作:

import axios from 'axios';
import { NotificationStateStore } from '../components/Notification/Notification.store';

export function useApi() {
    const api = axios.create({
        baseURL: import.meta.env.VITE_BACKEND_URL,
    });

    api.interceptors.response.use(null, responseErrorHandler);

    return { api };
}

function responseErrorHandler(error) {
    const { actions } = NotificationStateStore;

    actions.showNotification({
        color: 'error',
        text: 'Something went wrong, please try again ...',
    });
    return Promise.reject(error);
}

Notification组件使用新的状态结构,并在应用程序根组件中呈现它:

import { Alert, Snackbar, SnackbarCloseReason } from '@mui/material';
import { useStore } from '@nanostores/react';
import { NotificationStateStore } from './Notification.store';

export function Notification() {
    const { actions, states } = NotificationStateStore;
    const notificationState = useStore(states.notification);
    const handleClose = (
        event: Event | React.SyntheticEvent<any, Event>,
        reason?: SnackbarCloseReason,
    ) => {
        if (reason === 'clickaway') {
            return;
        }
        actions.closeNotification();
    };

    //  We need this if since if notificationState is undefined it cannot render the component.
    if (!notificationState) {
        return <></>;
    }

    return (
        <Snackbar
            open={notificationState.open}
            autoHideDuration={notificationState.autoHideDuration}
            onClose={handleClose}
        >
            <Alert
                onClose={handleClose}
                severity={notificationState.color}
                sx={{ width: '100%' }}
            >
                {notificationState.text}
            </Alert>
        </Snackbar>
    );
}

在您的应用程序或其他组件中,您要呈现通知:

function App() {
  // ...
  return (
    <>
      {/* Your other components */}
      <Notification />
    </>
  );
}

相关问题