【问题标题】:React Router how to return 404 page in case of dynamic routes expecting a parameter?如果动态路由需要参数,React Router如何返回404页面?
【发布时间】:2018-10-23 13:33:09
【问题描述】:

假设我在 Switch 中定义了以下路由:

<Switch>
    <Route path='/:pageId' component={Template} />
<Switch>

在模板中,我将 :pageId 传递给 API,它会返回该页面的内容。这一切都很好,但是如果我传递一个不存在的 :pageId 值,应用程序就会崩溃(就像我没有带有 slug“联系人”的页面)。

在这种情况下如何让它重定向到 404 页面以避免应用崩溃?

提前致谢。

【问题讨论】:

  • 您的应用在到达该路由并查询您的 API 之前不会知道 pageId 值是否存在。在这种情况下,我发现最好在服务器返回后在模板组件中的某处简单地呈现“找不到页面”。
  • 谢谢,是的,这就是我要做的,在模板组件上设置一个条件以加载 API 返回的内容,或者如果返回 null/undefined 则重定向到 404 页面。跨度>

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


【解决方案1】:

由于您只是将可变页面 id 传递给 Route 组件,而不是具体命名每个路由,因此您希望在服务器不返回任何内容的情况下让 Template 组件返回 404 页面。

在没有可用路径与给定路径匹配的情况下,Switch 将采用一个失败组件,但这仅适用于您使用特定命名路径的情况,即/users,而不是单一路径链接到可变页面名称。

【讨论】:

  • 通常这肯定适用于 404 页面,但在这种情况下,条件路由使任何内容都有效,例如“/thisPageDoesNotExist”仍然是第一条路由的有效路径,并且“thisPageDoesNotExist”将被传递作为 Params 中的 pageId。
  • 哦,该死的。你是完全正确的,很好的抓住。正确的解决方案是在Template组件中渲染“page not found”,然后。
  • 正确。如果你更新你的答案,我会支持你的帖子:)
  • 感谢 cmets。是的,如果您传递任何从 api 返回 null/undefined 作为参数的值,应用程序将会崩溃。我认为在模板组件中渲染“找不到页面”的建议是可行的。我认为在那里使用重定向也可以。
【解决方案2】:

一种可能的方法是利用 React 16 错误边界。然后,只要知道路由无效(只要它在渲染方法 IIRC 内),您就可以简单地抛出。

class RouteNotFoundError extends Error {
    constructor(...args) {
        super(...args)
        // extending Error is fickle in a transpiler world - use name check instead of instanceof/constructor
        this.name = "RouteNotFoundError"
    }
}

const RouteNotFoundBoundary = withRouter(
    class RouteNotFoundBoundary extends React.Component {
        constructor(props) {
            super(props)
            this.state = { routeNotFound: undefined }
        }
        componentWillReceiveProps(nextProps) {
            if (this.props.location !== nextProps.location) {
                this.setState({routeNotFound: false})
            }
        }
        componentDidCatch(e) {
            if (e.name === "RouteNotFoundError") {
                this.setState({routeNotFound: this.props.location.key})
            } else {
                throw e
            }
        }
        render() {
            if (this.state.routeNotFound === this.props.location.key) {
                return this.props.fallback || <div>Not found!</div>
            } else {
                return this.props.children
            }
        }
    }
)

const Template = props => {
    if (!allMyPages[props.match.params.pageId]) {
        throw new RouteNotFoundError()
    }

    return renderMyPage(allMyPages[props.match.params.pageId])
}

const Example = () => (
    <RouteNotFoundBoundary fallback={<div>Oh no!</div>}>
        <Switch>
            <Route path='/:pageId' component={Template}/>
        </Switch>
    </RouteNotFoundBoundary>
)

不确定这是否是个好主意,但当您知道路由是否有效的代码路径不是呈现 404 页面的最佳位置时,它可能会简化某些情况。

【讨论】:

    猜你喜欢
    • 2020-08-11
    • 2020-07-23
    • 2022-07-27
    • 2021-03-02
    • 2022-07-19
    • 2019-07-20
    • 2020-06-21
    • 2018-08-31
    • 2022-11-15
    相关资源
    最近更新 更多