Redux商店中的巨大物件

问题描述 投票:4回答:3

理想情况下,我们会在Redux中放入可能非常非常大(100k +行)的db查询的结果。

将结果放在redux中看起来有些过分,是否有一种干净的方法可以在redux存储中放置一种哈希或时间戳,并且能够在我的React组件中获取实际数据?

在Java中,我们可以以某种方式覆盖equals和hash,因此它不会做得非常平等,使得它更快。

react-redux
3个回答
2
投票

默认情况下,Redux不使用深度比较。 https://redux.js.org/faq/immutable-data#redux-shallow-checking-requires-immutability

在该页面上有相当多的信息,但有点蒸馏 - Redux仅检查对象引用是否已更改。

没有看到任何代码,很难说出具体问题是什么。有可能你以某种方式将你的对象放在树上太高,而Redux正在遍历你巨大物体的第一层上的键。如果是这种情况,只需将对象包装在Redux状态可能会有所帮助。

{
   huge: myHugeObject,
}

但实际上,这更像是一个绑匪。如果Redux正在遍历您的对象,那么您可能还没有正确使用它。

代码示例确实有助于诊断问题。


2
投票

这将是我对最终表现的建议。请记住,我自己没有对此进行测试,但如果我正确理解您的问题,那么我认为没有理由说它不起作用。

您需要存储100K行数据,理想情况下,您需要将此数据保留在客户端。这里最好的解决方案是使用IndexedDB,因为您可以像数据库一样进行读写,同时还有足够的存储空间。像Soleil推荐的那样,我建议你使用dexie与IndexedDB进行交互。你不需要它,但你肯定应该拥有它,因为它会给你带来很大的灵活性。

您还需要能够区分这些更改,如果不将工作推送到另一个线程上,那就不容易了。所以,建议如下:

  async function seedData() {
    // serialize your data, hopefully have unqiue id field on each row
    const hundredK = toJSON(await fetch(source));
    // IndexedDB doesn't have tremendous write speed, so it may be better to chunk your rows into
    // 10k intervals for  seem to perform the best but vary based on PC / browser implementation
    const db = new Dexie("myDataSource");
    // set version of Indexed to use (1 is preferred for best compatibility)
    // and set the indexes
    db.version(1).stores({
      animals: 'id,type'
    });
    let mice = [];
    for (let i = 0; i < hundredK.length; i++) {
      mice.push({
        id: i,
        species: hundredK[i].species,
        type: hundredK[i][0].type,
        facts: {
          someText: "this could come from hundredK, but I'll hardcode it",
          someNumber: i
        }
      });
    }
  }

所以现在数据在IndexedDB中,你可以随时查询它。现在,您需要一种方法将性能较重的部件推送到另一个线程。幸运的是有redux-worker

import reducer from './reducers';
import task from './task';
import { createWorker } from 'redux-worker';

let worker = createWorker();
worker.registerReducer(reducer);
worker.registerTask('DIFF_IT', function (a) {
  // do your diffing and expensive functions
  task(a);
});

让你的工人生效

  ...
  import { applyWorker } from 'redux-worker';
  // you can't have any external dependencies for your worker, so bundle them or find a way to inline them
  const worker = new Worker('./script.js') // alternatively inline an async function it with `greenlet-with-edge`
  const enhancer = compose(applyMiddleware(thunk, logger), applyWorker(worker));
  const store = createStore(rootReducer, {}, enhancer);

将您的数据库传递到您的组件,并挂钩更新。应用你的行动

// all in dexie docs
this.props.db.animals.hook('updating', (modifications, key, obj, tran) => {
  if ("species" in modifications) {
    this.props.actions.task(modifications.species, key, obj, tran);
  }
})

0
投票

您的主要关注点似乎是性能,尽管我会考虑评论中提到的建议,即:使用较小的有效负载,您需要将大量数据渲染到反应组件中,并且您需要它具有高性能,要实现这一点,你需要使用一个窗口组件,这将只渲染可见的行,并按需渲染其他所有内容,使渲染真正长的数据集真正高效,查看https://bvaughn.github.io/react-virtualized/并将数据传递给组件

© www.soinside.com 2019 - 2024. All rights reserved.