Redux存储中的巨大对象

时间:2019-02-20 14:30:24

标签: react-redux

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

将结果放入redux是一种过大的杀伤力,是否有一种干净的方法将某种哈希或时间戳放入redux存储中并能够在React组件中获取实际数据?

在Java中,我们可以以某种方式覆盖equals和hash,这样它就不会做深层的equals,从而使其更快。

3 个答案:

答案 0 :(得分:2)

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

该页面上有很多信息,但有一些提炼-Redux仅检查对象引用是否已更改。

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

{
   huge: myHugeObject,
}

但实际上,这更多是创可贴。如果Redux正在遍历您的对象,则您可能不太正确地使用它。

代码示例确实可以帮助诊断问题。

答案 1 :(得分:2)

这是我对最终性能的建议。请记住,我自己尚未对此进行测试,但是如果我正确理解了您的问题,那么我就没有理由不解决它。

您需要存储10万行数据,理想情况下,您需要将此数据保留在客户端。这里最好的解决方案是使用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);
  }
})

答案 2 :(得分:0)

您的主要关注点似乎是性能,尽管我会遵循​​注释中提到的建议,即:使用较小的有效负载,您需要将大量数据呈现到react组件中,并且需要它要实现高性能,您需要使用一个窗口组件,这将仅呈现可见行,并根据需要呈现其他所有内容,从而使真正长的数据集呈现真正的性能,调查https://bvaughn.github.io/react-virtualized/并将数据传递给组件