更改网址后,组件未重新呈现

时间:2020-10-11 16:33:32

标签: reactjs react-hooks react-router-dom

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的新手,所以我可能会缺少一些相当简单的内容。

1 个答案:

答案 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的函数将在将渲染提交到屏幕后运行。