进入路线更改的页面顶部
默认情况下,React路由器不会在更改路线后将您带到新组件的顶部,而是像导航到新页面之前的页面位置一样。为了解决此问题,我们将在src
文件夹中的辅助文件夹helpers
中创建ScrollToTop
JavaScript文件,并在下面添加代码。
import { useEffect } from "react"
import { useLocation } from "react-router-dom"
const ScrollToTop = () => {
const { pathname } = useLocation()
useEffect(() => {
window.scrollTo(0, 0)
}, [pathname])
return null
}
export default ScrollToTop
我们从useLocation()
钩上破坏了当前位置的pathname
,并在组件中添加了一个useEffect()
钩。 useEffect()
钩具有pathname
作为其依赖性。在每个页面上,该页面都将被迫滚动到顶部。
此指令将在App
组件中使用:
import React from "react"
import { BrowserRouter } from "react-router-dom"
import ScrollToTop from "./helpers/ScrollToTop";
function App() {
return (
<BrowserRouter>
<ScrollToTop />
<App />
</BrowserRouter>
);
}
使用谴责
辩论是一种编程模式,其中执行执行昂贵或耗时的操作的某个功能通常会延迟特定时间(通常在几秒钟内)来提高应用程序的性能。
需要一个延迟参数,该参数确定在执行任务之前将等待多长时间。这样的任务可以包括在列表中搜索或最重要的是执行异步请求。
通常用于限制用户仍在输入时对API的不必要调用的数量。
与VUE不同,在React中使用的调试并不是那么简单。那里有很多解决方案,其中一些使用useMemo
和useCallback
的挂钩。
这就是我能够解决这个问题的方式:
让我们在helpers
文件夹中创建一个useDebounce
文件。
import { useState, useEffect } from "react"
const useDebounce = (value, delay) => {
const [debouncedValue, setDebouncedValue] = useState(value)
useEffect(
() => {
const handler = setTimeout(() => {
setDebouncedValue(value)
}, delay)
return () => {
clearTimeout(handler)
}
},
[value, delay]
)
return debouncedValue
}
export default useDebounce
-
我们创建了一个
useDebounce
函数,该函数采用两个参数,value
adelay
。这是我们要扣除的价值,以及我们要在更改此值以毫秒之前要延迟多长时间。 -
然后将
value
存储在useState
钩中。 -
useEffect
挂钩接收一个setTimeout
函数,该函数在更改value
之前根据delay
参数的值延迟。 -
delay
和value
参数也是useEffect
依赖项。 -
之后,
setTimeout
被清除或中止,useEffect
也已退出。 -
只有在一个或两个依赖性变化时,
useEffect
钩才能再次运行。
以下是useDebounce
函数的用例。
import React, { useEffect, useState } from "react"
import useDebounce from "./utils/useDebounce"
const Universities = () => {
const [data, setData] = useState([])
const [term, setTerm] = useState("")
const debouncedTerm = useDebounce(term, 500)
const search = name => {
fetch(`http://universities.hipolabs.com/search?name=${name}`)
.then(res => res.json())
.then(data => {
setData(data)
console.log(data)
})
}
const clear = () => {
setData([])
setTerm("")
}
useEffect(() => {
search(debouncedTerm)
}, [debouncedTerm])
return (
<div>
<div className="relative w-[98%] mx-auto">
<input
type="text"
autoComplete="off"
onChange={e => setTerm(e.target.value)}
value={term}
placeholder="Search movies"
style={{
backgroundColor: " rgb(229 231 235)",
color: "rgb(17 24 39)",
width: "100%",
padding: "1rem",
}}
/>
<button onClick={() => clear()}>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
style={{ cursor: "pointer", width: "5rem", height: "5rem" }}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
{data.map((item, index) => (
<div key={index}>{item.name}</div>
))}
Demonstrating debounce with asynchronous call for a university api.
</div>
)
}
我们使用较早创建的useDebounce
函数拒绝了term
状态,并在search
函数和TH useEffect
阵列依赖项中使用了debouncedTerm
。
保护路线
与VUE不同,React不提供针对没有某些身份验证和授权的用户的路线的开箱即用解决方案。
为了证明这一点,我将使用上下文API创建一个auth
状态和一个toggleAuth
函数,该函数模仿了可以在应用程序中任何地方使用的用户的登录和注销。
//AuthContext.js
import React, { createContext, useState } from "react"
export const AuthContext = createContext()
const AuthContextProvider = ({ children }) => {
const [auth, setAuth] = useState(false)
const toggleAuth = () => setAuth(!auth)
return (
<AuthContext.Provider value={{ auth, toggleAuth }}>
{children}
</AuthContext.Provider>
)
}
export default AuthContextProvider
我们现在必须创建一个ProtectedRoutes
文件。在此文件中,我们提取auth
状态,并根据auth
的值确定是否显示路线或导航用户到登录页面,也就是说,如果是true
或false
。
<Outlet>
应在父路由元素中使用以呈现其子路由元素。这允许嵌套UI在渲染子路线时出现。如果父路线完全匹配,则它将渲染子索引路由或没有索引路线。
不要忘记用AuthContextProvider
包装您的应用程序。
import React from "react"
import { Navigate, Outlet } from "react-router-dom"
import { AuthContext } from "../context/AuthContext"
const ProtectedRoutes = () => {
const { auth } = useContext(AuthContext)
return auth ? <Outlet /> : <Navigate to="/login" />
}
export default ProtectedRoutes
我们现在可以在路线定义中使用受保护的路线。
<Route element={<ProtectedRoutes />}>
<Route element={<Home />} path="/" exact />
<Route element={<Products />} path="/products" />
</Route>
我们提供了ProtectedRoutes
文件作为路由组件的元素组件支柱,它将包裹我们要保护的组件。
结论
总而言之,构建React单页应用程序可以带来自己的一系列挑战。其中一些挑战可能包括保护路线,使用审问以及在路线更改时进入页面顶部。但是,有几种解决这些问题的解决方案。
可以使用身份验证和授权技术来解决保护路线。这样可以确保只有身份验证的用户才能访问应用程序的某些部分。辩论的使用有助于通过减少函数调用的数量来防止性能问题和超负荷。可以使用scrollto窗口方法来实现路由更改的页面顶部。
通过应用这些解决方案,开发人员可以改善其React Spa的功能和用户体验。