当前位置: 首页 > 面试题库 >

懒惰地在react-router onEnter挂钩中添加新的史诗是一种有效的做法吗?

周承天
2023-03-14
问题内容

当使用终极版,可观察到有反应的路由器,这将是有意义的异步的文档中添加新的史诗按照指示在这里中路由变化中的OnEnter反应路由器的钩子?

./epics/index.js

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { combineEpics } from 'redux-observable';

import { epic1 } from './epic1'
import { epic2 } from './epic2'

export const epic$ = new BehaviorSubject(combineEpics(epic1, epic2));
export const rootEpic = (action$, store) =>
    epic$.mergeMap(epic =>
        epic(action$, store)
    );

export {
    rootEpic
};

… routes / SomePath / index.js

import { epic$ } from './../../../../epics/index'
import { epic3 } from './../../../../epics/epic3'

module.exports = {
    path: 'some-path',
    getComponent( location, cb ) {
        require.ensure( [], ( require ) => {
            cb( null, require( './components/SomePath' ) )
        } )
    },
    onEnter() {
        epic$.next(epic3)

    }
}

对Rxjs来说是非常新的东西,可以进行redux观察。这似乎可行,但是奇怪:1.在这种情况下,每次我们导航到/ some-
path时,会再次将epic3添加到rootEpic吗?2.如果我要console.log将哪些史诗添加到rootEpic中,我该怎么做?

编辑以回应@JayPhelps

我可以要求澄清几点吗?

  1. registerEpic fn很棒。我一直在使用.distinct()运算符来解决重复的史诗注册问题,如下所示:

export const epic$ = new BehaviorSubject(combineEpics(epic1, epic2)).distinct()

这是否是处理惰性史诗注册的同等有效/好方法,如果不是,您能否解释一下原因?

  1. 我正在使用具有require.ensure和ES6导入的create-react-app(它们是不同的导入方式吗?),基本上,我复制粘贴了react-router的巨大应用示例,该示例具有require.ensure代码,但是无处不在否则,我在文件顶部使用import语句。

因此,将史诗和顶部的registerEpic
fn导入似乎可行,同时将路径放入require.ensure第一个参数似乎也可行。如果我使用require.ensure和import语句,这会使事情变得混乱吗?如果我使用require.ensure加载路由所需的所有内容,这是否意味着我删除了该路由组件的嵌套(无路由)组件内的所有导入语句?

    import { epic3 } from './../../epics/epic3'
    import { epic4 } from './../../epics/epic4'
    import { registerEpic } from './../../epics/index'

    module.exports = {
        path: 'my-path',
        getComponent( location, done ) {
            require.ensure( [], ( require ) => {
               registerEpic(addYoutubeEpic)
                registerEpic(linkYourSiteEpic)
                done( null, require( './components/Edit' ) )
            } )
        }
    }
  1. 关于在“ getComponent” fn中注册史诗以进行异步加载-我认为在这里进行同步加载实际上是可取的,这样直到史诗被注册后路由组件才呈现。如果用户尝试在路线上执行某些操作(例如获取一些详细信息或提交表单),而该操作要求该史诗已被注册而该史诗尚未被注册,该怎么办?

  2. 在react-router module.export声明之外是否还有其他地方适合懒惰地注册史诗?由于我项目中的许多路线都不需要登录,因此登录并不总是会触发路线更改。但是,在用户登录后,应该注册许多史诗。目前,我正在通过在authReducer中设置令牌变量来以一种非常愚蠢且可能是错误的方式进行操作,但是它所做的只是调用一个函数注册新的史诗:

        './../reducers/authReducer.js'

    import { greatEpic } from './../epics/fetchFollowListEpic'
    import { usefulEpic } from './../epics/fetchMyCollectionsEpic'
    // and a few more 
    import { registerEpic } from './../epics/index'

    const addEpics = () => {
        registerEpic(greatEpic)
         registerEpic(usefulEpic)
         ...etc
    }

    export default function reducer( state = {
        loggingIn: false,   
        loggedIn: false,
        error: '',
    }, action ) {
        switch ( action.type ) {
            case "LOGIN_SEQUENCE_DONE": {
                return {
                    ...state,
                    aid: setAuthToken(action.payload),
                    loginFailed: false,
                    addEpics: addEpics(),
                }

            }

我可以想象,loginEpic将是注册史诗的最佳场所,而不是reducer。(我在github上找到了您的登录示例,因此看起来很熟悉)。是正确的,还是我完全不在基地?我知道.concat()是同步的,并且我知道redux是同步的-
我不确定registerEpics()是否是同步的,但是使用reducer注册史诗SEEMS可以正常工作-
这是否意味着registerEpics是同步的?还是只是说事情发展得如此之快以至无所谓?还是仅由于我对导入语句有一些基本的误解以及webpack如何处理我必须进一步研究的代码拆分而起作用?

    ./../epics/loginEpic

    export const loginEpic = action$ =>
        action$.ofType("LOGIN")
            .mergeMap(action =>

                Observable.fromPromise(axios.post('webapi/login', action.payload))
                    .flatMap(payload =>
                        // Concat multiple observables so they fire sequentially
                        Observable.concat(
                            // after LOGIN_FULILLED
                            Observable.of({ type: "LOGIN_FULFILLED", payload: payload.data.aid }),                   
                            // ****This is where I think I should be registering the epics right after logging in. "ANOTHER_ACTION" below depends upon one of these epics****     
                            Observable.of({type: "ANOTHER_ACTION", payload: 'webapi/following'}),
                            Observable.of({type: "LOGIN_SEQUENCE_DONE"}),
                        )
                    )
                    .startWith({ type: "LOGIN_PENDING" })
                    .takeUntil(action$.ofType("LOGIN_CANCELLED"))
                    .catch(error => Observable.of({
                        type: "LOGIN_REJECTED",
                        payload: error,
                        error: true
                    }))
            );

问题答案:

在这种情况下,每次我们导航到/ some-path时,会再次将epic3添加到rootEpic吗?

如果您使用的反应路由器和做代码分裂,你居然要添加您的内部必要的史诗getComponent钩, 没有
onEnter钩。这是因为该getComponent钩子允许异步加载该路由所需的资源,不仅是组件,还包括任何史诗,化require.ensure()简工具等。如果您使用,这会告诉webpack将这些项目拆分为单独的包,这样它们就不会包含在原始条目一个-
因此不要将这些文件导入其他任何地方,否则您将对此予以否定!

因此,大致来说,这是一个可能如下所示的示例:

路线/SomePath/index.js

    import { registerEpic } from 'where/ever/this/is/epics/index.js';

    export default {
      path: 'some-path',

      getComponent(location, done) {
        require.ensure(['./components/SomePath', 'path/to/epics/epic3'], require => {
          // this is where you register epics, reducers, etc
          // that are part of this separate bundle
          const epic = require('path/to/epics/epic3').epic3;
          registerEpic(epic);

          done(null, require('./components/SomePath'));
        });
      }
    };

在哪里/曾经/这个/是/epics/index.js

    import { BehaviorSubject } from 'rxjs/BehaviorSubject';
    import { combineEpics } from 'redux-observable';

    import { epic1 } from './epic1';
    import { epic2 } from './epic2';

    const epicRegistry = [epic1, epic2];
    const epic$ = new BehaviorSubject(combineEpics(...epicRegistry));

    export const registerEpic = (epic) => {
      // don't add an epic that is already registered/running
      if (epicRegistry.indexOf(epic) === -1) {
        epicRegistry.push(epic);
        epic$.next(epic);
      }
    };

    // your root epic needs to use `mergeMap` on the epic$ so any
    // new epics are composed with the others
    export const rootEpic = (action$, store) =>
      epic$.mergeMap(epic =>
        epic(action$, store)
      );

我创建了一个注册功能,以确保您不添加已经添加的史诗。getComponent 每当 您输入该路由时,react-router都会调用
一次 ,因此这一点很重要,因此您不会有两个正在运行的同一史诗实例。

但是请注意,当涉及到之类的东西时,我的代码做出了一些错误的假设require('path/to/epics/epic3').epic3。您的epic3实际上是作为命名属性导出的吗?我以为是这样,但是我注意到您正在执行此操作done(null,require('./components/SomePath')),如果您使用export defaultES2015 /
ES6模块导出该组件,我的直觉告诉我可能无法正常工作。如果是这样,则实际上是在require('./components/SomePath').default--note
.default!因此,虽然我的代码是一般性想法,但您应该特别注意require路径,导出的属性等。您说它似乎可以正常工作,所以也许您的设置有所不同(或者我只是错了,呵呵)

  1. 如果我想console.log将哪些史诗添加到rootEpic中,我该怎么做?

最简单的方法是登录registerEpic实用程序:

    export const registerEpic = (epic) => {
      // don't add an epic that is already registered/running
      if (epicRegistry.indexOf(epic) === -1) {
        epicRegistry.push(epic);
        console.log(`new epic added: ${epic.name}`);
        epic$.next(epic);
      }
    };

但是您也可以.do()epic$主题上使用RxJS 运算符更具体地执行此操作:

    export const rootEpic = (action$, store) =>
      epic$
        .do(epic => console.log(`new epic added: ${epic.name || '<anonymous>'}`))
        .mergeMap(epic =>
          epic(action$, store)
        );

但是,这将<anonymous>是第一次记录,因为通过的第一个是combineEpics(...epicRegistry)将多个史诗合并为一个匿名史诗的结果。



 类似资料:
  • 我有一个小的井字游戏,一切都很好,除了我正在努力寻找在代码中放置完成功能的位置。让我给你看; 这基本上是整个游戏,我在另一个文件中有一个整理函数,就像这样; 完成功能也可以正常工作,但是由于useState是异步工作的,我知道这一点,我正在努力把它放在哪里。如果我把点击功能放在里面,它就不能对新的状态做出反应,只能对之前的状态做出反应。如果我把外面加上只是if语句,它会说渲染太多,因为我正在设置获

  • 我有一个数据表的问题-懒加载。我认为问题是在IdiomasBean.java(TableBean.java),如果我把: 我得到了正确的数据表,但是<代码>按排序、筛选和不起作用。 我得到:java。lang.NullPointerException这里是堆栈跟踪: 下面是代码的其余部分: 指数xhtml diomasBean.java 懒散的数据模型。JAVA IdiomasBo.java 习语

  • 问题内容: 我在Linux上编写了一个C程序,该程序可以分配内存,并在一个循环中运行它,而TOP没有显示任何内存消耗。 然后我对该内存做了一些操作,而TOP确实显示了内存消耗。 当我分配内存时,我真的是“获取内存”,还是有一个“惰性”内存管理,仅当使用时才给我内存? (还有一个选项,当我使用它时,TOP只知道内存消耗,因此我不确定。) 谢谢 问题答案: 在Linux上,malloc使用sbrk()

  • 问题内容: 我刚刚阅读了React的新功能挂钩。了解有关钩子的信息, 但我无法使用它。它给我错误。 我目前正在使用16.6.0版 终于我明白了钩子。 我导入为Fun并在app.js文件中使用 我犯的错误是我没有安装React v16.7.0-alpha,所以我使用npm安装了add react @ next react-dom @ next。 谢谢 问题答案: 编辑: 挂钩是16.8.0版的一部分

  • 太长,读不下去了如何模拟或使用带有数组的道具强制重置我的组件? 我正在实现一个组件,它显示一个计时器,并在达到零时执行回调。目的是让回调更新对象列表。后一个组件由新的React钩子和组成。 包含对计时器启动时间和剩余时间的引用。设置每秒钟调用一次的间隔,以更新剩余的时间,并检查是否应该调用回调。 该组件并不意味着重新安排计时器,或者在间隔达到零时保持间隔,它应该执行回调并空闲。为了让计时器刷新,我

  • 问题内容: 我最近读到了Python 3的一个好处是它很懒。那就更好了 而不是 我很好奇的是如何使用这种懒惰。如果生成映射对象,例如,如何访问生成的操作/列表中的特定元素。在我所见过的几乎所有文档中,他们都会做类似或的事情(据我所知),它放弃了惰性概念,因为它隐式将地图转换为列表。 我想我正在寻找的是能够以与我可以懒惰地懒惰地生成地图对象类似的方式使用地图对象的能力,并且可以在没有巨大计算量的情况