React on Rails社交项目:实现Ventbox弹窗式/vent路由功能
解决方案:让Ventbox弹窗显示并保留/vent路由
1. 修改NavBar组件
原来的Ventbox被NavLink包裹,点击会触发路由跳转。把NavLink换成普通的div,保留样式和图标,这样点击只会触发弹窗:
import React from 'react' import { NavLink } from "react-router-dom" import { navData } from "./navData.js"; import styles from "./styles/navbar.module.css" import { useState } from "react"; import KeyboardDoubleArrowRightIcon from '@mui/icons-material/KeyboardDoubleArrowRight'; import KeyboardDoubleArrowLeftIcon from '@mui/icons-material/KeyboardDoubleArrowLeft'; import Ventbox from './Ventbox' import CreateIcon from '@mui/icons-material/Create'; export default function NavBar() { const [open, setopen] = useState(false) const toggleOpen = () => { setopen(!open) } return ( <div className={open?styles.sidenav:styles.sidenavClosed}> <button className={styles.menuBtn} onClick={toggleOpen}> {open? <KeyboardDoubleArrowLeftIcon />: <KeyboardDoubleArrowRightIcon />} </button> {navData.map(item =>{ return <NavLink key={item.id} className={styles.sideitem} to={item.link}> {item.icon} <span className={styles.linkText}>{item.text}</span> </NavLink> })} {/* 替换NavLink为普通div,避免路由跳转 */} <div className={styles.sideitem}> <CreateIcon /> <Ventbox style={styles.linkText} /> </div> </div> ) }
2. 优化Ventbox组件
清理无用的useNavigate和to props,新增全屏遮罩确保弹窗在全局显示:
import React, { useState } from "react"; import './styles/Ventbox.css' function Ventbox({style}) { const [popup,setPop] = useState(false); const [content, setContent] = useState(""); const [textLimit, setTextLimit] = useState(250); const handleClickOpen = () => { setPop(!popup); } const closePopup = () => { setPop(false); } const handleChange = e => { setContent(e.target.value); setTextLimit(250 - e.target.value.length); } const handleSubmit = async e => { e.preventDefault(); if (content.length > 250) { alert("Text limit reached"); } else { try { const response = await fetch(`/posts`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: content }) }); const data = await response.json(); console.log(data); // 提交成功后关闭弹窗 closePopup(); } catch (error) { console.error(error); } } } return( <div> <span onClick={handleClickOpen} className={style}>Vent</span> {popup && ( <div className="ventbox-overlay"> <div className="popup"> <div className="popup-header"> <h1>What's on your mind?</h1> <button className="delete-button" onClick={closePopup}>X</button> </div> <div> <form onSubmit={handleSubmit}> <input className="textbox" placeholder="Enter text here" value={content} onChange={handleChange} maxLength={250} /> <p>Characters remaining: {textLimit}</p> <button className="post-button"type="submit">Post</button> </form> </div> </div> </div> )} </div> ) } export default Ventbox;
3. 补充Ventbox全局样式(Ventbox.css)
确保弹窗遮罩覆盖整个页面,层级高于其他内容:
.ventbox-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 1000; } .popup { background-color: white; padding: 2rem; border-radius: 8px; width: 90%; max-width: 500px; position: relative; } .textbox { width: 100%; min-height: 100px; margin: 1rem 0; padding: 0.5rem; border: 1px solid #eee; border-radius: 4px; } .post-button { background-color: #1da1f2; color: white; border: none; padding: 0.5rem 1.5rem; border-radius: 20px; cursor: pointer; } .delete-button { position: absolute; top: 1rem; right: 1rem; border: none; background: none; font-size: 1.2rem; cursor: pointer; }
4. 保留/vent端点
在路由配置文件(如App.js)中添加/vent路由,渲染独立的发布页面:
import { Routes, Route } from 'react-router-dom'; import Ventbox from './components/Ventbox'; // 新建VentPage组件 function VentPage() { return ( <div style={{ padding: '2rem', maxWidth: '600px', margin: '0 auto' }}> <h1>Create a New Vent</h1> <Ventbox /> </div> ); } // 路由配置中添加 <Routes> {/* 其他已有路由 */} <Route path="/vent" element={<VentPage />} /> </Routes>
修改完成后,点击NavBar的Vent按钮会在当前页面弹出发布框,直接访问/vent也能看到独立的发布界面,完全满足需求。
内容的提问来源于stack exchange,提问作者Jason Tran
相关产品推荐
相关产品推荐

