React / Redux同构/服务器端渲染和媒体查询

我开始创build一个基于Node的同构React / Redux应用程序。 该项目的一个要求是基于“移动”和“桌面”视图的“adapative”渲染特定组件。 我已经实现了Redux动作和Reducer来存储有关用户视图的屏幕信息(基于媒体查询 – “小”,“中”,“大”)的状态。 在调整状态/商店得到更新。 默认状态是“小”。

const defaultState = { isMobile: true, isTablet: false, isDesktop: false, sizes: { small: true, medium: false, large: false, huge: false, }, }; 

在需要根据屏幕尺寸在两个不同版本中呈现“自适应”的组件中,我简单地做一个:

如果(小)返回变化1

如果(中)返回变化2

所有的工作。

现在我面临两个问题:

  1. 我的应用程序是同构的,这意味着标记也呈现服务器端。 服务器不知道用户的浏览器和媒体查询。 所以,因为我的默认状态是“小”,服务器将始终呈现“variation1”。 节点服务器是该站点的入口点。 它看起来像渲染需要“延迟”(中间件?),服务器需要从React应用程序获取“传递”之前从客户端获取一些有关浏览器宽度的信息。 任何想法如何解决这个问题?

  2. 因为渲染是基于状态的,所以即使在浏览器大小是“桌面”的情况下,在加载“变化1”之后几秒钟总是可以看到(闪烁)。 这是因为在使用当前屏幕宽度更新状态之前,JS检测需要几毫秒的时间。 我认为这与上面的问题和默认状态一起玩。

我找不到任何解决scheme1,但我想必须有一些同构和响应/自适应。

您可以从服务器的头部获取用户代理,然后使用返回数据的reducer发送带有用户代理信息的redux动作,这样您可以检测手机/平板电脑/桌面/等用户是否相应地进行渲染

一个很难解决的问题在我看来有很多“依赖”的解决scheme。 🙂

我是react-sizemereact-component-queries ,两个库来帮助响应组件,并遇到类似的问题,你在你的问题中描述。 根据我的经验,我发现解决您的一个问题往往会影响到另一个问题。 我将在下面详细描述我的经验,详细说明我的意思。

我试图先解决你的“问题2”

渲染由于默认状态而闪烁是我在创buildreact-sizeme库时所react-sizemereact-sizeme是一个更高阶的组件,它获取组件的大小,然后将其传递到组件中。 根据尺寸,当然可以select渲染不同的组件,因此可以使用更新闪烁,除非您碰巧碰到默认状态甜蜜点。 我通过改变react-sizeme来“征服”这个,最初渲染一个空的占位符,以获得可用的宽度/高度,然后只渲染你的组件,给它“适当的”宽度/高度。 这对我来说非常有效。 我不再看到ComponentBob被渲染,只能被卸载,并立即渲染ComponentFoo。

然后“问题1”出现了

react-sizeme开始获得普及,最终我有一个图书馆的消费者希望在服务器端渲染上下文中使用它。 但是由于修复了问题1,服务器端渲染会产生大量的空白内容(即我所说的占位符)。 将有效载荷传递给浏览器后,占位符逻辑将启动并最终将大小数据发送到组件,并将呈现它。 这是不理想的,因为你从根本上废除了做SSR的任何好处。 我和这个用户一起工作,我们决定最好的方法是允许将react-sizemeconfiguration为在“SSR模式”下运行。 基本上,这需要放弃占位符渲染,并允许呈现默认的组件,以便您不会在初始服务器响应中获得空白页面,但是您可以轻松地再次遭受组件闪烁问题!

Aaaaaaaaaah! 看到这里的影响锯! 🙁

所以基本解决一个问题直接影响另一个问题。


我继续给这个想法,我相信可能最好的办法是尝试获取用户的浏览器宽度/高度的第一个要求。 这基本上意味着渲染一个简单的实用程序来消除这些信息,然后将其提交回服务器,以呈现用户的初始请求。 然后,您可以使用宽度/高度,并将其传递到整个组件树(一直进行math计算),以确定每个组件的可用高度/宽度。 超级棘手的东西在这里,但可能工作。

另一个危险当然就是google只是为初始请求索引一个空白页面(即,用来消除初始宽度/高度的util的空白呈现)。 你将不得不尝试使用一些聪明的HTTP响应代码,如redirect等,以确保谷歌跟踪适当的渲染输出。


对不起,这可能不是你正在寻找的答案,但希望我的经验有所帮助,或提供某种灵感。 如果你想出了一些有趣的实验,请保持我张贴。 我很乐意与你合作。