【问题标题】:How can I use React Router's withRouter HOC inside my own higher order component (HOC)?如何在我自己的高阶组件 (HOC) 中使用 React Router 的 withRouter HOC?
【发布时间】:2019-01-07 00:42:31
【问题描述】:

我有一个高阶组件,它使用 React Router 提供的 location.search 属性来构造一个 queryParams 对象并将其作为属性传递给它的包装组件。

function withQueryParams(WrappedComponent) {
    return (props) => {
        const queryParams = myUtils.parseParams(props.location.search); // props.location provided by React Router
        const newProps = {
            ...props,
            queryParams: queryParams
        }

        return <WrappedComponent {...newProps} />
    }
}

export default withQueryParams

我会这样使用它:

class MyComponent extends React.Component { ... }

export default withQueryParams(MyComponent)

当然,我会将MyComponent 包裹在一条路线中:

<Route path="/mycomponent" component={MyComponent} />

但回到我的withQueryParams HOC,我想确保props.location 始终可用,这意味着我希望它始终拥有来自 React Router 的道具。输入withRouter,它本身就是一个由 React Router 提供的 HOC,你可以使用它来使这些 props 可用。

在我的withQueryParams HOC 中使用withRouter 以确保props.location 可用的最佳方式是什么?

谢谢。

【问题讨论】:

  • 根据 组件的文档 (reacttraining.com/react-router/web/api/Route/component),任何由 组件渲染的组件都会传递三个 props:match、location、history。这些是备受追捧的道具,我相信当相关组件不是由 组件直接呈现的组件时,使用 withRouter 提供这些道具。
  • 是的,没错。这里的目标是让withQueryParams 不具有对 React Router 道具的这种隐式依赖。当它用于不是由&lt;Route&gt; 呈现的组件时,它不应该中断。这就是为什么我想将它包装在 withRouter 中,这样它总是有可用的道具,即使它不在实际的 &lt;Route&gt; 的上下文中。

标签: javascript reactjs react-router react-redux


【解决方案1】:

您可以使用两个 HOC 包装您的组件,即 withRouterwithQueryParams。您可以使用recompose 来使用这些 HOC 包装您的组件。我为此创建了一个沙箱。 https://codesandbox.io/s/y493w29lz

首先,点击https://y493w29lz.codesandbox.io/main。这将在屏幕上显示以下输出。

MainComponent
SubComponent
"No Query Params available"

现在,尝试传递一个查询参数,例如https://y493w29lz.codesandbox.io/main?query=hello。可以看到查询参数打印在屏幕上。

MainComponent
SubComponent
Query Params = {"query":"hello"}

这里,SubComponent 组件不是由 Route 渲染的,但它正在接收查询参数,因为我们使用 withRouterwithQueryParms HOC 包装了这个组件。

export const SubComponent = compose(
  withRouter,
  withQueryParams
)(SubComponentView);

现在,如果您仅通过点击 URL https://y493w29lz.codesandbox.io/sub?query=hello 来呈现 SubComponent。它将显示以下输出。

SubComponent
Query Params = {"query":"hello"}

希望这能回答您的问题。 :)

【讨论】:

  • 非常感谢您的详细回复。是的,我知道我可以在组件级别将withQueryParams 包装在withRouter 中(在您的情况下为MainComponentSubComponent),但我的问题是如何包含withRouter inside withQueryParams.js 文件,所以它是一种封装单元。这样我就不必担心每次使用它时都用withRouter 包装它。这有意义吗?
  • 是的,这完全有道理。 @nschwan94 的回答正是如此。 :)
【解决方案2】:
function withQueryParams(WrappedComponent) {
        return withRouter((props) => {
           const queryParams = myUtils.parseParams(props.location.search); // props.location provided by React Router
           const newProps = {
               ...props,
               queryParams: queryParams
           }

           return <WrappedComponent {...newProps} />
        })
}

export default withQueryParams

【讨论】:

  • 如果不声明realQueryParams,难道不能达到同样的效果吗?如果您只是将return (props) ... 包裹在withRouter 中会怎样? IE。 return withRouter((props) =&gt; ...)
猜你喜欢
  • 1970-01-01
  • 2019-02-05
  • 1970-01-01
  • 2018-09-14
  • 1970-01-01
  • 2017-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多