在 Redux 应用程序中预加载 initialState 的最佳实践是什么?

IT技术 reactjs redux
2021-04-05 00:25:15

我目前对使用 Flux 提出的 hack 不满意,现在使用 Redux 在我的商店中填充 initialState。

我总是在初始页面加载时发送 JSON 的有效负载。在我的某些应用程序中,通用 JavaScript 不是一个选项,因为它们并非都由 Node.js 支持。我想重点关注有关如何将数据预加载到客户端的“最佳实践”和模式。然后,我觉得转移到服务器是微不足道的。

以下是我目前在工作中和其他一些使用 Redux 的玩具应用程序中所做的事情的要点:

https://gist.github.com/kevinold/5767bb334472b7e2bfe3

总结一下:

  • 我正在随页面向下发送全局变量
  • 在 componentDidMount() 中,我正在分派“接收”和处理各种数据的操作。(这些“接收”方法用于在通过请求操作异步获取这些数据位时处理这些数据位,我在这里重新利用它们,因为我已经有了这些数据。)

这有效,我们没有遇到任何问题,但感觉就像我不太满意的黑客。另外,我觉得 Redux 的初始状态对我这样做并不满意。

根据http://rackt.org/redux/docs/recipes/ServerRendering.html和“客户端”部分,我可以将 initialState 传递给我的商店。

这是我正在帮助的另一个项目(KeystoneJS)的补丁。我将它的 Keystone 对象传递到 initialState 中:

https://github.com/kevinold/keystone/commit/6f80c2f6f1e5c081361369a8bb31b75f1e62460f#diff-cd8e9933209e834b0519a0257bcfa914R8

虽然这不工作,你可以看到,我不得不与我的整体combinedReducers输出的形状(https://github.com/kevinold/keystone/commit/6f80c2f6f1e5c081361369a8bb31b75f1e62460f#diff-b4b498ca92c4d05e050b45c725c26f9d),或者我会得到控制台警告等。

我可能在处理这个问题时非常懒惰,但是在添加/更改与减速器相关的任何内容(添加减速器,它们的组成方式等)时,我试图限制必须更新另一条数据。

我意识到我可能必须这样做才能将这个初始状态正确地放入减速器中。

我目前正在消化(https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/client.js#L25如何处理它的初始状态。

我真的很感激一些关于对其他人有用的“最佳”和“现实世界”实践的反馈。

1个回答

我不完全理解这个问题,但我会尽力回答。

在 componentDidMount() 中,我正在分派“接收”和处理各种数据的操作。(这些“接收”方法用于在通过请求操作异步获取这些数据位时处理这些数据位,我在这里重新利用它们,因为我已经有了这些数据。)

这是派遣他们的坏地方。如果您选择调度操作而不是直接提供初始状态,请在渲染之前执行此操作换句话说,在创建商店后立即执行此操作!这样你就不会渲染初始的空白状态。

虽然这不工作,你可以看到,我不得不与我的整体combinedReducers输出的形状(https://github.com/kevinold/keystone/commit/6f80c2f6f1e5c081361369a8bb31b75f1e62460f#diff-b4b498ca92c4d05e050b45c725c26f9d),或者我会得到控制台警告等。

您不应该initialState手动创建对象。你应该在服务器上创建一个 Redux 存储,在dispatch那里用数据预填充它的动作,当它准备好时,调用store.getState()以检索你想要传递给客户端的状态。在客户端上,您将从全局变量中读取它,并使用它创建客户端存储实例。换句话说,您永远不必手动创建——您initialState应该在服务器上使用 获取它store.getState(),将它传递给客户端,然后用它创建一个商店。

所以我不明白你描述的问题。如果您的减速器名称或嵌套更改,它也会在服务器上更改。你不需要做任何事情来“修复它”——如果你在客户端和服务器上都使用 Redux,它们的状态结构将匹配。

我真的很感激一些关于对其他人有用的“最佳”和“现实世界”实践的反馈。

  1. 如果您在服务器上使用 Redux,请按上述方式预填充存储,并将其状态传递给客户端。在这种情况下,您需要使用 的initialState参数createStore()

  2. 如果您出于某种原因不在服务器上使用 Redux无论如何都想预填充数据(例如,您可能使用 Node 以外的其他东西),那么调度操作的方法是您的下一个最佳选择,因为它不需要您的后端知道状态形状。在这种情况下,您应该将这些操作作为 JSON 传递给客户端,并创建商店后立即dispatch()所有这些操作传递给客户端

@jamesemanon 从存储中读取并将其作为initialState 传递。订阅存储,偶尔将当前状态写入存储。
2021-05-24 00:25:15
谢谢丹,这确实有意义并且有帮助。
2021-05-26 00:25:15
@KevinOld 如果您不在服务器上使用 Redux,我建议您保留当前分派单独操作的方法,这样您就无需将状态形状硬编码到服务器中。只要确保在渲染前调度!
2021-06-11 00:25:15
@DanAbramov 你有实践中选项#2 的例子吗?我正在开发一个前端 Redux 应用程序,它带有一个无法使用 Redux 的 .NET 后端。
2021-06-13 00:25:15
我正在使用 Rails 和 Phoenix 后端,而不是在服务器上使用 Redux。正如您在gist.github.com/kevinold/5767bb334472b7e2bfe3中看到的,我有多个来自服务器的 JSON 对象。将这些组合到服务器上的 initialState 中肯定会有所帮助。非常感谢您对这个主题的反馈和澄清!
2021-06-21 00:25:15