React初始渲染时数组对象过滤结果不显示,重渲染后正常
初始渲染过滤预订列表不显示的问题解决
问题描述
页面首次加载时,过滤后的预订数组无法展示;但保存代码触发热重载后,过滤结果能正常显示。尝试将过滤结果存入常量后调用setFilteredBookings,问题仍未解决。
问题根源
在useEffect的异步请求逻辑中,调用setBookings(bookingsresponse.data)后立刻用bookings状态数组做过滤操作。但React的useState更新是异步批量处理的,此时bookings还是初始的空数组[],过滤结果自然为空,导致初始渲染没有内容。热重载时组件重新初始化,bookings已缓存了之前的数据,过滤就能正常执行。
解决方案
方案1:直接使用接口返回的数据过滤
不要依赖刚更新的bookings状态,直接用接口返回的原始数据做过滤,再更新filteredBookings状态:
function Booking() { const name = localStorage.getItem('name'); const email = localStorage.getItem('email'); const [bookings, setBookings] = useState([]); const [filteredBookings,setFilteredBookings] = useState([]); useEffect( () => { const fetchBookings = async() => { try{ const customerIDResponse = await axios.get(`http://localhost:5000/getUserID/${name}/${email}`); const bookingsresponse = await axios.get(`http://localhost:5000/getBookings/${customerIDResponse.data.SQLdata[0].customerid}`); const fetchedBookings = bookingsresponse.data; setBookings(fetchedBookings); // 直接用接口返回的fetchedBookings过滤,避开异步状态更新的延迟 const currentTime = new Date().getTime(); const filtered = fetchedBookings.filter(booking => { const bookingTime = new Date(booking.bookingdate).getTime(); return bookingTime >= currentTime; }); setFilteredBookings(filtered); } catch(err){ alert("Uncaught error contact owner of website"); } } fetchBookings(); },[]) const handleDelete = async (bookingid) => { try{ await axios.delete(`http://localhost:5000/deleteBooking/${bookingid}`); window.location.reload(); } catch(err){ alert("Uncaught error contact owner of website"); console.log(err); } } return ( <div className="main"> <Navbar/> <div className="current-bookings-container"> <div className="bookings-header">Bookings in the next week for {name}</div> <div className="current-bookings"> {filteredBookings.map( booking => ( <div className="booking" key={booking.bookingid}> <h1>Booking ID: {booking.bookingid}</h1> <p>Your booking date: {booking.bookingdate}</p> <p>The booking time is: {booking.bookingtime}</p> <button className="delete" onClick={()=>handleDelete(booking.bookingid)}>Delete</button> <button className="update"><Link to={`/booking/update/${booking.bookingid}`}>Update</Link></button> </div> ))} </div> </div> <button className="create-booking"><Link to="/booking/create">Create a Booking</Link></button> </div> ) }
方案2:去掉filteredBookings状态,渲染时实时计算(更推荐)
直接在渲染阶段根据bookings状态和当前日期计算过滤结果,避免维护额外状态导致的同步问题:
function Booking() { const name = localStorage.getItem('name'); const email = localStorage.getItem('email'); const [bookings, setBookings] = useState([]); useEffect( () => { const fetchBookings = async() => { try{ const customerIDResponse = await axios.get(`http://localhost:5000/getUserID/${name}/${email}`); const bookingsresponse = await axios.get(`http://localhost:5000/getBookings/${customerIDResponse.data.SQLdata[0].customerid}`); setBookings(bookingsresponse.data); } catch(err){ alert("Uncaught error contact owner of website"); } } fetchBookings(); },[]) const handleDelete = async (bookingid) => { try{ await axios.delete(`http://localhost:5000/deleteBooking/${bookingid}`); window.location.reload(); } catch(err){ alert("Uncaught error contact owner of website"); console.log(err); } } // 渲染时实时计算过滤后的列表 const currentTime = new Date().getTime(); const filteredBookings = bookings.filter(booking => { const bookingTime = new Date(booking.bookingdate).getTime(); return bookingTime >= currentTime; }); return ( <div className="main"> <Navbar/> <div className="current-bookings-container"> <div className="bookings-header">Bookings in the next week for {name}</div> <div className="current-bookings"> {filteredBookings.map( booking => ( <div className="booking" key={booking.bookingid}> <h1>Booking ID: {booking.bookingid}</h1> <p>Your booking date: {booking.bookingdate}</p> <p>The booking time is: {booking.bookingtime}</p> <button className="delete" onClick={()=>handleDelete(booking.bookingid)}>Delete</button> <button className="update"><Link to={`/booking/update/${booking.bookingid}`}>Update</Link></button> </div> ))} </div> </div> <button className="create-booking"><Link to="/booking/create">Create a Booking</Link></button> </div> ) }
内容的提问来源于stack exchange,提问作者Dylan Bose
相关产品推荐
相关产品推荐

