Material UI 搜索输入触发侧边栏打开功能失效如何解决
问题根因
toggleDrawer为柯里化函数,设计用于返回事件监听回调,直接调用toggleDrawer("right", true)只会生成一个未执行的函数,不会触发状态更新- 对props
searchInput的变更监听逻辑放在组件渲染顶层,无法在props更新时触发对应逻辑,且渲染过程中直接修改状态会导致异常重渲染 - 原有获取消息数据的
useEffect逻辑错误,将数据请求放在了组件卸载的清理函数中,无法正常拿到数据
修复方案
- 新增
useEffect监听searchInput的变化,输入内容非空时直接修改抽屉打开状态 - 修正数据获取的
useEffect逻辑,将数据请求放到组件挂载阶段执行 - 移除组件顶层的无效if判断
import { Fragment, useEffect, useState } from "react"; import Box from "@mui/material/Box"; import Drawer from "@mui/material/Drawer"; import Button from "@mui/material/Button"; import List from "@mui/material/List"; import Divider from "@mui/material/Divider"; import ListItem from "@mui/material/ListItem"; import ListItemIcon from "@mui/material/ListItemIcon"; import ListItemText from "@mui/material/ListItemText"; import InboxIcon from "@mui/icons-material/MoveToInbox"; import MailIcon from "@mui/icons-material/Mail"; import { collection, getDocs } from "@firebase/firestore"; import db from "../../firebase"; export default function SearchDrawer({ searchInput }) { const [messages, setMessages] = useState([]); const [state, setState] = useState({ right: false, }); // 修正后的数据获取逻辑,挂载时执行请求 useEffect(() => { const getMessages = async () => { const channels = await getDocs(collection(db, "channels")); channels.forEach(async (channel) => { const msgs = await getDocs( collection(db, "channels", channel.id, "messages") ); msgs.forEach((msg) => { setMessages((prev) => [...prev, msg.data()]); }); }); }; getMessages() // 卸载时清空消息 return () => setMessages([]) }, []); // 新增监听searchInput的副作用,输入时打开侧边栏 useEffect(() => { if (!!searchInput) { setState(prev => ({...prev, right: true})) } }, [searchInput]) const toggleDrawer = (anchor, open) => (event) => { if ( event.type === "keydown" && (event.key === "Tab" || event.key === "Shift") ) { return; } setState({ ...state, [anchor]: open }); }; const list = (anchor) => ( <Box sx={{ width: anchor === "top" || anchor === "bottom" ? "auto" : "45vw" }} role="presentation" onClick={toggleDrawer(anchor, false)} onKeyDown={toggleDrawer(anchor, false)} > <List> {["Inbox", "Starred", "Send email", "Drafts"].map((text, index) => ( <ListItem button key={text}> <ListItemIcon> {index % 2 === 0 ? <InboxIcon /> : <MailIcon />} </ListItemIcon> <ListItemText primary={text} /> </ListItem> ))} </List> <Divider /> <List> {["All mail", "Trash", "Spam"].map((text, index) => ( <ListItem button key={text}> <ListItemIcon> {index % 2 === 0 ? <InboxIcon /> : <MailIcon />} </ListItemIcon> <ListItemText primary={text} /> </ListItem> ))} </List> </Box> ); return ( <> <Fragment key={"right"}> <Button onClick={toggleDrawer("right", true)}>{"right"}</Button> <Drawer anchor={"right"} open={state["right"]} onClose={toggleDrawer("right", false)} > {list("right")} </Drawer> </Fragment> </> ); }
内容的提问来源于stack exchange,提问作者Eric Harutyunyan
相关产品推荐
相关产品推荐

