React SSR:我的组件如何在其渲染方法中获取 URL 搜索 URL 参数

React SSR : How can my component get the URL search URL parameters in its render method

我不清楚在读取服务器上的 React 应用程序时如何让请求的搜索参数在组件中可用。

客户端渲染

在客户端呈现的 React 应用程序中,我知道如何将请求的搜索参数传递到用于该路由的组件。

下面的代码在我的 CSR 应用程序中。参见第二条路线,我正在获取搜索参数“b”的值并将其作为“名称”传递到我的组件 属性。

<Router>
  <Switch>
    <Route exact path="/" component={Home} />

    <Route
      exact
      path="/a/:id"
      render={(props) => {
        const params = new URLSearchParams(props.location.search);
        const b = params.get('b');
        return ( <MyComp id={props.match.params.id} name={b} /> );
      }}
    />
  </Switch>
</Router>

因此,如果我的 URL 是

http://host:port/a/b=George

MyComp 的

this.props.b

将return“乔治”。组件可以在它的“render”方法中得到这个值

render(){
    const { name } = this.props;
}

服务器端渲染

在我的 SSR 应用程序中,路由是使用路由配置定义的

export default [
  {
    ...Home,
    path: '/',
    exact: true,
    title: 'Home Screen',
  },
  {
    ...MyComp,
    path: '/a/:id',
    exact: true,
    title: 'My Component'
  },
];

这里没有可用的道具,所以与 CSR 应用程序不同,我无法获取“props.location.search”并发送到组件。

我的服务器和客户端渲染器中使用了这个 Routes 对象:

<Provider store={store}>
  <StaticRouter .... }>
    <div>{renderRoutes(Routes)}</div>
  </StaticRouter>
</Provider>


<Provider store={store}>
  <BrowserRouter ....>
    <div>{renderRoutes(Routes)}</div>
  </BrowserRouter>
</Provider>,

在我的组件“render”方法中,我无法获取“b”参数的值。 “this.props.location”在其“搜索”中没有任何价值 属性。

如何使搜索 url 参数可用于 React SSR 应用程序中我的组件渲染方法。

我确实想知道是否可以做类似下面的事情,但显然在这种情况下“props”是未知的

{
    ...MyComp,
    path: '/a/:id',
    exact: true,
    title: 'My Component',
    name: new URLSearchParams(props.location.search).get('b')
  },

我知道我可以从“req.query”获取我的 Express 服务器代码中的信息。但是我对该值所能做的就是将它传递给我的组件“loadData”方法,但这并不能使它在我的渲染方法中可用。

server.get('*', (req, res) => {
  const store = createStore();
    
  console.log(req.query) // this gives me the value of "b"

  // I could pass req.query to the component's loadData but that does not gain me anything
  const promises = matchRoutes(Routes, req.path)
    .map(({ route, match }) => (
        route.loadData ? route.loadData(store, match, req.query) : null)
      );

关于如何使搜索 URL 参数可用于我的路由组件的呈现方法的任何想法?

我找到了解决这个问题的方法。我不确定它是最好的解决方案,但它似乎在服务器端和客户端渲染中都有效。

服务器端

在服务器端,在 Express Server 文件中,将“req.query”添加到 Routes 对象中的每个 Route,就在其用于 MatchRoutes

之前
import Routes from '../pages/Routes';
...

server.get('*', (req, res) => {

    Routes.forEach((r)=>{
      r.queryParams = req.query;
    });

    const promises = matchRoutes(Routes, req.path)

    ....

这使得“queryParams”在渲染服务器端时在组件中可用,因此可以获得“b”查询参数的值

render() { 
    const { route } = this.props;    
    const { queryParams } = route;
    
    const name = queryParams.b;
    ....

客户端

客户端路由不会填充“queryParams”,但“this.props.location.search”具有值,因此我们可以从那里获取值。

componentDidMount() {
    const { location } = this.props;
    const params = new URLSearchParams(location.search);
    const name = params.get('b');
    this.setState({ name });

正在渲染名字

在组件的渲染方法中,您必须检查它是在客户端还是服务器端渲染,并使用相关数据。

render() {  
    // server side rendering values
    const { route } = this.props;    
    const { queryParams } = route;
    // client side rendering values
    const { name } = this.state;

    let title = name; // will be undefined in SSR
    if (queryParams){
      // SSR set the name
      title = queryParams.b;
    }

服务器端的另一种解决方案是将 req.query 添加到包含调用匹配路由的组件方法时创建的所有数据的上下文对象。

const context = { data, requestQueryParams: req.query };

此上下文对象随后包含在服务器端路由器上

<StaticRouter context={context} ...>

然后组件可以在服务器端从这个上下文对象中获取任何数据

  const { staticContext } = this.props;
  data = staticContext.data;
  const myQueryParamValue = staticContext.requestQueryParams.myQueryParamName;