React模态框表单输入无法点击问题排查求助
React模态框表单输入交互异常排查与修复
问题现象
- 模态框表单仅顶部第一个输入框可点击,其余输入框无法交互
- 缩小浏览器宽度后,第二个输入框恢复可点击状态
- 问题出现时间与引入
react-toastify同步,已排除后端问题
相关代码
Modal组件
import {useState} from 'react'; const Modal = ({open, close, submitForm}) => { const [task, setTask] = useState(''); const [cat, setCat] = useState(''); const [deadline, setDeadline] = useState(''); const handleSub = (e) => { e.preventDefault(); submitForm({'task': task, 'cat': cat, 'ddln': deadline}); setTask(''); setCat(''); setDeadline(''); } // 原渲染逻辑:仅当open为false时返回模态框,open为true时无返回值 if(!open){ return ( <div className="myOverlay"> <div className="myModal"> <strong onClick={close}>X</strong><br /> <form method="post" onSubmit={handleSub} > <div className="form-group"> <label htmlFor="exampleInputEmail1">Task</label> <input type="text" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter task" name="task" value={task} onChange={(e) =>setTask(e.target.value)}/> </div><br /> <div className="form-group"> <select className="form-control" defaultValue={cat} id="inlineFormCustomSelectPref" name="cat" onChange={(e) =>setCat(e.target.value)}> <option>Task category</option> <option value="Tech">Tech</option> <option value="Marketing">Marketing</option> <option value="Financial">Financial</option> <option value="Admin">Admin</option> </select> </div> <br /> <div className="form-group"> <label htmlFor="exampleInputPassword1">Deadline</label> <input type="date" className="form-control" id="exampleInputPassword1" placeholder="Deadline" name="ddln" value={deadline} onChange={(e) =>setDeadline(e.target.value)}/> </div> <div className="form-check"> <input type="checkbox" className="form-check-input" id="exampleCheck1" /> <label className="form-check-label" htmlFor="exampleCheck1">Make Task Active</label> </div> <br /> <input type="submit" className="btn btn-dark" value="Submit"/> </form> </div> </div> ); } } export default Modal
Root组件
import { Outlet } from 'react-router-dom'; import { useState } from 'react'; import Sidebar from './Sidebar'; import Modal from './Modal'; import { toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; const Root = () => { const [ modal, setModal ] = useState(true); const [ page, setPage ] = useState('home'); const addFormHandle = async (formData) => { const res = await fetch('http://127.0.0.1:8000/api/tasks/add', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(formData), }); if (res.ok) { toast.success('Task added successfully', { position: "top-right", autoClose: 5000, hideProgressBar: false, closeOnClick: true, pauseOnHover: true, draggable: true, progress: undefined, theme: "dark", }); } else { toast.error('Task failed to add please check network connection!!!', { position: "top-right", autoClose: 5000, hideProgressBar: false, closeOnClick: true, pauseOnHover: true, draggable: true, progress: undefined, theme: "dark", }); } setModal(true); } return( <div className='row'> <div className="col-md-2"> <Sidebar page={setPage} /> </div> <div className="col-md-10"> <main className="main-sec container"> <Outlet /> </main> <Modal open={modal} close={()=>setModal(true)} submitForm={addFormHandle} /> </div> <div className="myContainer"> <button className="btn btn-dark fixed-button" onClick={()=>setModal(false)}>Add Task</button> </div> </div> ) } export default Root;
App组件
import { createBrowserRouter, createRoutesFromElements, Route, Outlet, RouterProvider} from 'react-router-dom'; import { useState } from 'react'; import Sidebar from './Components/Sidebar'; import Cards from './Components/Main/Cards'; import Table from './Components/Main/Table'; import Modal from './Components/Modal'; import Deadlines from './Components/Deadlines'; import Home from './Components/Home'; import Tasks from './Components/Tasks'; import Inoives from './Components/Inoives'; import Root from './Components/Root'; import DataLoada from './DataLoada.js'; import { ToastContainer } from 'react-toastify'; function App() { const router = createBrowserRouter( createRoutesFromElements( <Route path="/" element={<Root />}> <Route index element={<Home />} /> <Route path="/deadlines" element={<Deadlines />} /> <Route path="/tasks" element={<Tasks />} loader={DataLoada} /> <Route path="/invoices" element={<Inoives />} /> </Route> ) ); return ( <> <RouterProvider router={router} /> <ToastContainer /> </> ); } export default App;
修复方案
1. 修正Modal组件的渲染逻辑
原代码中当open为true时,Modal组件没有返回任何内容,会导致React渲染异常,影响DOM结构层级。调整逻辑,确保组件始终返回有效JSX:
const Modal = ({open, close, submitForm}) => { // ...state和handleSub保持不变 // 当open为true时,不显示模态框,返回null if(open){ return null; } // 否则渲染完整模态框 return ( <div className="myOverlay"> {/* 原模态框内容 */} </div> ); }
2. 调整模态框的CSS层级,避免被覆盖
react-toastify的默认z-index为9999,会覆盖模态框元素,导致输入框无法点击。给模态框添加足够高的z-index:
/* 模态框遮罩层 */ .myOverlay { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background-color: rgba(0, 0, 0, 0.5); z-index: 10000; /* 高于ToastContainer的默认层级 */ display: flex; justify-content: center; align-items: center; } /* 模态框主体 */ .myModal { background-color: #fff; padding: 2rem; border-radius: 8px; z-index: 10001; /* 高于遮罩层 */ position: relative; width: 90%; max-width: 500px; }
3. 可选:调整ToastContainer的层级
如果不想修改模态框层级,也可以降低ToastContainer的z-index,确保模态框在上方:
// App.js中修改ToastContainer <ToastContainer zIndex={9999} />
(注:若模态框z-index设为10000,则Toast的9999会在下方)
问题根源分析
- 模态框渲染逻辑错误导致组件状态异常,影响DOM渲染的稳定性
react-toastify的ToastContainer默认z-index过高,覆盖了模态框的输入元素,导致无法交互- 浏览器宽度变化时,元素布局重排可能临时改变层级关系,出现部分输入框可点击的现象
内容的提问来源于stack exchange,提问作者Lwazi
相关产品推荐
相关产品推荐

