Router
的配置如下所示
App.js
<Router>
<Switch>
<Route exact path="/" render={() => <Home />} />
<Route exact path="/products/:productId" component={ ProductDetail } />
<Redirect to="/" />
</Switch>
</Router>
ProductDetail
组件的外观如下
ProductDetail.js
export const ProductDetail = ({ match }) => {
const productId = match.params.productId;
useEffect(() => {
dispatch(fetchProductById(productId));
}, [productId, dispatch]);
const product = useSelector((state) => selectProductById(state, productId));
return(<.....>)
}
现在,当我从Home
导航到ProductDetail
时,一切正常。但是,如果我尝试直接访问URL http://localhost:3000/products/someId
,则该组件不会呈现,并且不会调用useEffect
挂钩。
我已经阅读了Router
文档,并说
当您使用组件(而不是下面的渲染器或子组件)时,路由器将使用React.createElement从给定的组件中创建一个新的React元素。
这是否意味着应该渲染新创建的组件(在我的情况下为ProductDetail
)并调用钩子?
我是React
的新手,所以我可能会缺少一些相当简单的内容。
答案 0 :(得分:1)
如评论中所述,当直接导航到ProductDetail
组件时,该产品仍将不在商店中。 useEffect
钩子会启动产品的加载,但是直到完成加载为止,product
将是未定义的(或为null,或其他取决于减速器的名称)。您需要单独处理这种情况。
最简单的处理方法是呈现某种类型的加载指示器,例如
export const ProductDetail = ({ match }) => {
const productId = match.params.productId;
useEffect(() => {
dispatch(fetchProductById(productId));
}, [productId, dispatch]);
const product = useSelector((state) => selectProductById(state, productId));
if (!product) {
return <p>Loading...</p>
}
return(<.....>)
}
此外,正如注释中所提到的,当渲染组件时,也会发生钩子。该组件不会等待useEffect
钩子启动的操作完成。来自React's docs:
传递给
useEffect
的函数将在将渲染提交到屏幕后运行。