繁体   English   中英

服务器端 React Initial Render 导致重复的异步调用

[英]Server Side React Initial Render causes duplicated async calls

我在服务器上使用 react-router 2.0。 我的一些顶级路由组件依赖于要获取的异步数据并使用 Redux 来管理状态。 为了解决这个问题,我使用了一个静态的fetchData()方法来返回一个Promise.all的异步操作,如官方 Redux 文档中所建议 它工作得很好——来自服务器的初始渲染带有 Redux 存储中的适当数据。

我的问题来自如何编写这些异步调用,这种方式既适用于服务器上的初始渲染,又适用于客户端上的后续渲染,因为加载了不同的路由。 目前,我在顶级组件的componentDidMount()调用静态fetchData()方法,但是一旦组件安装在客户端上,这将导致fetchData() 这是我从另一个导航到路由时想要的,但不是在初始渲染时,因为我们已经在服务器上进行了这个调用。

我一直在努力以一种方式编写我的数据获取逻辑:

  1. 仅在服务器上的初始渲染上调用一次,而不是在客户端初始渲染上调用
  2. 当用户从另一条路线导航时将呈现。

我正在考虑将像{ serverRendered: true }这样的道具注入初始组件,但在调用renderToString()时我只能访问<RouterContext> 我查看了源代码,但似乎我也无法从该 JSX 标记传递该属性。

我想我的问题是:

  1. 有没有办法在<RouterContext>注入一个属性,以便它向下传递到“父”顶级路由组件? 如果不在<RouterContext> ,是否有另一种方法可以注入该属性?
  2. 如果#1 不可能,是否有更好的方法来处理fetchData()以便初始渲染不会导致fetchData()在服务器和客户端上都被调用?

这是我的 server.jsx、fetchData() 处理中间件和示例顶级组件的代码示例。

我遇到了同样的问题。 使用setTimeout清除某些全局值或检查 Redux 存储中是否存在数据对我来说并不好。

我决定检查加载了哪些路径初始数据,将此数组作为全局值并检查componentDidMount路由匹配。

我的服务器 index.js

const pathsWithLoadedData= []; // here I store paths

const promises = matchRoutes(Routes, req.path)
    .map(({ route }) => {
        if (route.loadData) {
            // if route loads data and has path then save it
            route.path && pathsWithLoadedData.push(route.path);
            return route.loadData(store);
        } else {
            return Promise.resolve(null);
        }
    })

我的渲染模板

<body>
   ...
   <script> 
      window.INITIALLY_LOADED_PATHS = ${JSON.stringify(pathsWithLoadedData)};
   </script>
   ...   
</body>

一些 componentDidMount 函数

componentDidMount () {
    if (!wasFetchedInitially(this.props.route.path)) {
        this.props.fetchUsers();
    }
}

和帮手

export const wasFetchedInitially = componentPath => {
    const pathIndex = window.INITIALLY_LOADED_PATHS.indexOf(componentPath);
    if (pathIndex < 0) return false;

    window.INITIALLY_LOADED_PATHS.splice(pathIndex, 1);
    return true;
};

我注入一个全局变量window.__INITAL_FROM_SERVER__ = true并从客户端使用setTimeout清除它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM