You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Snackbar组件使用children属性时报错,寻求解决办法

Snackbar组件显示错误排查与解决

问题概述

开发的用于数据添加成功通知的Snackbar组件无法正常显示,出现以下三类错误:

  • Warning: Failed prop type: Invalid prop 'children' supplied to 'ForwardRef(Alert)', expected a ReactNode
  • Error: Objects are not valid as a React child (found: object with keys {}). If you meant to render a collection of children, use an array instead.
  • console.js:288 The above error occurred in the <div> component:

已尝试设置默认消息但无效,怀疑是后端返回数据或组件使用位置导致问题,组件代码如下:

import React, { createContext, useContext, useState, forwardRef } from "react";
import Snackbar from "@mui/material/Snackbar";
import MuiAlert from "@mui/material/Alert";

const Alert = forwardRef(function Alert(props, ref) {
  return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
});

const SnackbarContext = createContext();

export const useSnackbar = () => {
  return useContext(SnackbarContext);
};

const SnackbarProvider = ({ children }) => {
  const [snackbar, setSnackbar] = useState({
    open: false,
    message: "",
    severity: "info",
  });

  const showSnackbar = (message = "", severity = "info") => {
    setSnackbar({ open: true, message: message || "No message", severity });
  };

  const handleClose = (event, reason) => {
    if (reason === "clickaway") {
      return;
    }
    setSnackbar({ ...snackbar, open: false });
  };

  return (
    <SnackbarContext.Provider value={showSnackbar}>
      {children}
      {snackbar.open && snackbar.message && (
        <Snackbar
          open={snackbar.open}
          autoHideDuration={6000}
          onClose={handleClose}
          anchorOrigin={{ vertical: "top", horizontal: "center" }}
        >
          <Alert
            onClose={handleClose}
            severity={snackbar.severity}
            sx={{ width: "100%" }}
          >
            {snackbar.message}
          </Alert>
        </Snackbar>
      )}
    </SnackbarContext.Provider>
  );
};

export default SnackbarProvider;

错误原因分析

核心问题是**snackbar.message被设置为了对象而非字符串**:

  1. 当调用showSnackbar时,如果传入的是后端返回的空对象(比如接口返回{}),或者误传了整个响应对象而非具体的消息字符串,就会导致React无法渲染对象类型的子元素,触发"Objects are not valid as a React child"错误。
  2. 第一个警告是Alert组件期望接收合法的ReactNode(字符串属于合法类型,对象不属于),本质也是message类型错误导致的。

解决方案

1. 严格校验并转换message类型

修改showSnackbar函数,确保最终存入state的message是字符串:

const showSnackbar = (message = "", severity = "info") => {
  let displayMessage = "No message";
  // 优先处理字符串类型
  if (typeof message === 'string' && message.trim()) {
    displayMessage = message;
  } 
  // 如果是对象,尝试提取内部的message字段(适配后端返回格式)
  else if (typeof message === 'object' && message !== null) {
    displayMessage = message.message || "操作完成";
  }
  setSnackbar({ open: true, message: displayMessage, severity });
};

2. 渲染层添加兜底处理

在Alert组件内部添加类型判断,确保渲染的是合法内容:

<Alert
  onClose={handleClose}
  severity={snackbar.severity}
  sx={{ width: "100%" }}
>
  {typeof snackbar.message === 'string' ? snackbar.message : "操作提示"}
</Alert>

3. 检查调用场景

确认调用useSnackbar()的地方,是否正确传入了字符串:

  • 如果是后端接口返回,确保取的是响应中的消息字段(比如response.data.message而非response.data);
  • 避免直接传入空对象、undefined等非字符串类型的值。

修改后的完整代码

import React, { createContext, useContext, useState, forwardRef } from "react";
import Snackbar from "@mui/material/Snackbar";
import MuiAlert from "@mui/material/Alert";

const Alert = forwardRef(function Alert(props, ref) {
  return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
});

const SnackbarContext = createContext();

export const useSnackbar = () => {
  return useContext(SnackbarContext);
};

const SnackbarProvider = ({ children }) => {
  const [snackbar, setSnackbar] = useState({
    open: false,
    message: "",
    severity: "info",
  });

  const showSnackbar = (message = "", severity = "info") => {
    let displayMessage = "No message";
    if (typeof message === 'string' && message.trim()) {
      displayMessage = message;
    } else if (typeof message === 'object' && message !== null) {
      displayMessage = message.message || "操作完成";
    }
    setSnackbar({ open: true, message: displayMessage, severity });
  };

  const handleClose = (event, reason) => {
    if (reason === "clickaway") {
      return;
    }
    setSnackbar({ ...snackbar, open: false });
  };

  return (
    <SnackbarContext.Provider value={showSnackbar}>
      {children}
      {snackbar.open && (
        <Snackbar
          open={snackbar.open}
          autoHideDuration={6000}
          onClose={handleClose}
          anchorOrigin={{ vertical: "top", horizontal: "center" }}
        >
          <Alert
            onClose={handleClose}
            severity={snackbar.severity}
            sx={{ width: "100%" }}
          >
            {typeof snackbar.message === 'string' ? snackbar.message : "操作提示"}
          </Alert>
        </Snackbar>
      )}
    </SnackbarContext.Provider>
  );
};

export default SnackbarProvider;

内容的提问来源于stack exchange,提问作者Rafi rizqullah ramadhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 09:39:49