使用React Router和React Hooks在非路由组件中绕过更新阻止程序

时间:2019-01-08 19:06:43

标签: javascript reactjs react-router react-router-v4 react-hooks

我正在将React Router与通用Page组件一起使用,该组件基于slug从WP Rest API中获取内容。我可以直接通过url和路由作品访问这些页面。

我的页脚组件中有一个小菜单,它使用React Router <Link>组件链接到使用Page组件的各个页面。

当我单击这些链接时,URL正在更新,但是Page组件未使用更新的子弹重新呈现,因此没有获取正确的页面内容。

这绝对是更新阻止,如此处的React Router文档所述:https://reacttraining.com/react-router/web/guides/dealing-with-update-blocking

涵盖了大多数解决方案,但是在我的情况下,页脚组件不是Route,而是Layout组件的子组件,Layout组件也没有路由,并且包装了所有其他组件。

要解决此问题,文档建议我需要在组件树下发送React Router location道具。

我尝试使用withRouter向下导出组件树中的所有组件,该组件树应该向下传递此道具,但它不起作用。

当我在<Page>组件中单击<Link>时,如何更新<Footer>组件?

App.js中的路由:

<BrowserRouter>
    <Layout
        addToCart={addToCart}
        removeFromCart={removeFromCart}
        clearCart={clearCart}
        cart={cart}
        catalog={catalog}
    >
        <Switch>
            <Route exact path="/" render={() => <Home catalog={catalog} />} />
            <Route
                exact
                path="/catalog"
                render={() => (
                    <Catalog addToCart={addToCart} catalog={catalog} />
                )}
            />
            <Route path="/:slug" render={props => <Page {...props} />} />
            <Route
                path="/catalog/:category/:slug"
                render={() => (
                    <SingleProduct addToCart={addToCart} catalog={catalog} />
                )}
            />
        </Switch>
    </Layout>
</BrowserRouter>

Layout.js(简体):

<Layout>
    <Header />
    {children}
    <Footer />
<Layout

<Footer />中的链接:

<ul className="nostyle footer-links">
    <li>
        <Link to="/faq">FAQ</Link>
    </li>
    <li>
        <Link to="/about">About</Link>
    </li>
    <li>
        <Link to="/contact">Contact Us</Link>
    </li>
</ul>
//...
export default withRouter(Footer)

Page.js:

const Page = props => {
    const slug = props.match.params.slug
    const [page, setPage] = useState()

    const fetchPage = async () => {
        const result = await axios(
            `${params.liveUrl}${params.pages}?slug=${slug}`
        )
        setPage(result.data)
    }

    useEffect(() => {
        fetchPage()
    }, [])

    return (
        <Fragment>
            <div className="page" key={page[0].slug}>
                {page[0].content}
            </div>
        </Fragment>
    )
}

export default withRouter(Page)

因此,如果我直接访问/faq/about,它会按照路线中的指示加载<Page />组件,并进入子弹,一切都会正确显示。

但是,如果我单击<Footer />中的链接之一,则URL会更改,但是<Page />组件不会被新的信息刷新,从而不会刷新正确的页面数据。如果我重新加载页面,则会加载正确的数据。

更改路线后,如何强制<Page>组件进行更新?

请注意,我使用的是React钩子,而不是Redux。

谢谢!

1 个答案:

答案 0 :(得分:1)

您需要为Page组件设置唯一键,以便每次更改键时都会呈现此组件的新实例。

假设子弹头是唯一的,则可以执行以下操作:

<Page key={props.match.params.slug} {...props} />

或者,您也可以像这样:

<Page key={window.location.pathname} {...props} />