redux thunk和应用程序内体系结构-希望仅在视图中呈现视图,并在单独的组件中分派GET操作

redux thunk和应用程序内体系结构-希望仅在视图中呈现视图,并在单独的组件中分派GET操作,redux,react-redux,redux-thunk,separation-of-concerns,Redux,React Redux,Redux Thunk,Separation Of Concerns,我在应用程序中使用react-redux和redux-thunk,我尝试做两件事: 我希望能够在两个组件中共享GET请求的结果。我知道您可以通过将这两个组件连接到商店来实现这一点,但我想这样做,如果用户登录到X页面,那么Y页面无法再次发出相同的GET请求(这两个组件是缩略图和旋转木马)。换句话说,GET请求应该发出一次(不是100%确定redux thunk的最佳实践是什么),每个组件都应该能够访问存储并在组件中呈现结果(这很简单,我也可以做到) 目前,GET请求是两个子视图组件的父级,这(我认

我在应用程序中使用react-redux和redux-thunk,我尝试做两件事:

  • 我希望能够在两个组件中共享GET请求的结果。我知道您可以通过将这两个组件连接到商店来实现这一点,但我想这样做,如果用户登录到X页面,那么Y页面无法再次发出相同的GET请求(这两个组件是缩略图和旋转木马)。换句话说,GET请求应该发出一次(不是100%确定redux thunk的最佳实践是什么),每个组件都应该能够访问存储并在组件中呈现结果(这很简单,我也可以做到)

  • 目前,GET请求是两个子视图组件的父级,这(我认为)没有意义。我只想在父视图中呈现子视图组件,而不是GET请求。如果不清楚,请阅读下面的代码

  • 这是父视图(Gallery),它有一个子组件,用于向redux发送操作(使用redux thunk),从而生成API(FetchImages):

    导入。。。
    导出默认函数库(){
    返回(
    ---->这是发出API请求并呈现两个子视图组件
    )  
    }
    
    这是FetchImages,它正在调度进行API调用的操作(FetchImages)

    import ...
    
    function FetchImages({ fetchImages, imageData }) {
    
      useEffect(() => {
        fetchImages()
      }, [])
    
        return imageData.loading ? (
          <h2>Loading</h2>
        ) : imageData.error ? (
          <h2>Something went wrong {imageData.error}</h2>
        ) : (
          <>
          <Thumbnail /> -----> these two are views that are rendered if GET request is successful
          <Carousel />
          </>
        )
    }
    
    const mapStateToProps = state => {
        return {
            imageData: state.images
        }
    }
    
    const mapDispatchToProps = dispatch => {  
        return {
            fetchImages: () => dispatch(fetchImages())
        }
    }
    
    export default connect(
      mapStateToProps, 
      mapDispatchToProps
      )(FetchImages)
    
    导入。。。
    函数FetchImages({FetchImages,imageData}){
    useffect(()=>{
    fetchImages()
    }, [])
    返回imageData.loading(
    加载
    ):imageData.error(
    出现错误{imageData.error}
    ) : (
    ----->这两个视图是在GET请求成功时呈现的
    )
    }
    常量mapStateToProps=状态=>{
    返回{
    imageData:state.images
    }
    }
    const mapDispatchToProps=调度=>{
    返回{
    fetchImages:()=>分派(fetchImages())
    }
    }
    导出默认连接(
    MapStateTops,
    mapDispatchToProps
    )(获取图像)
    
    我认为这样做更有意义:

    import ...
    
    export default function Gallery() {
    
      return(
        <>
    
          <GalleryTabs />
          <GalleryText />
    
          <div className="gallery-images-container">
            <Thumbnail />  -----> Thumbnail should be rendered here but not Carousel ( FetchImages here adds unnecessary complexity )   
          </div>
    
        </>
      )  
    }
    
    导入。。。
    导出默认函数库(){
    返回(
    ----->缩略图应该在这里呈现,而不是旋转木马(这里的FetchImages增加了不必要的复杂性)
    )  
    }
    
    tldr

  • 如果两个组件可以发送一个发出GET请求的操作,但每次用户访问网站时只能发送一次,那么应该遵循哪些最佳实践

  • 使用redux thunk,分离关注点的最佳实践是什么,以便子视图组件位于父视图组件内,以及子视图组件之间共享的更智能的组件(例如发出GET请求的调度操作)当用户登录页面时,视图和更智能的组件没有直接连接在一起时,是否会被调度


  • 我是一个noob,所以感谢您提供的任何帮助

    您的第一个问题:您的组件容器应该只发送它需要数据的操作。这个答案中没有介绍如何在state中存储异步结果,以及如何在稍后处理state中的结果,但是后面的示例使用了一个名为List的组件,该组件只调度获取数据页,选择数据页并在UI中转储数据页。如果数据已经处于状态,tunk操作将提前返回

    在生产应用程序中,您可能希望存储异步api结果,包括加载、错误、请求和一堆额外信息,而不是假设它存在或不存在

    第一个答案部分回答了你的第二个问题。组件容器应该只发送一个操作,指示它们需要数据,而不必知道已经存在、已经被请求的数据或其他任何东西

    可以使用以下代码对返回承诺的函数进行分组:

    //稍后解析承诺
    const later=(时间、结果)=>
    新承诺((决议)=>
    setTimeout(()=>解析(结果),时间)
    );
    //群承诺返回函数
    常量createGroup=(缓存)=>(
    fn,
    getKey=(…x)=>JSON.stringify(x)
    )=>(…参数)=>{
    const key=getKey(args);
    让result=cache.get(key);
    如果(结果){
    返回结果;
    }
    //无缓存
    结果=Promise.resolve(fn.apply(null,args))。然后(
    (r) =>{
    cache.resolved(key);//告诉缓存承诺完成
    返回r;
    },
    (e) =>{
    cache.resolve(key);//告诉缓存承诺完成
    退回承诺。拒绝(e);
    }
    );
    cache.set(键、结果);
    返回结果;
    };
    //永久内存缓存存储创建者
    常量createPermanentMemoryCache=(缓存=新映射())=>{
    返回{
    get:(key)=>cache.get(key),
    set:(键,值)=>cache.set(键,值),
    已解析:(x)=>x,//在承诺解析后不会删除缓存项
    };
    };
    //承诺完成时的临时内存缓存存储创建者
    //缓存密钥被删除
    const createTmpMemCache=()=>{
    常量映射=新映射();
    常量缓存=createPermanentMemoryCache(映射);
    cache.resolved=(key)=>map.delete(key);
    返回缓存;
    };
    //返回承诺的测试函数
    常量testPromise=(m)=>{
    log(`testpromise是用${m}`调用的);
    稍后返回(500米);
    };
    const permanentCache=createPermanentMemoryCache();
    const groupTestPromise=createGroup(permanentCache)(
    测试承诺,
    //请注意,这会导致对分组函数的所有调用
    //无论参数是什么,都将存储在键“p”下
    //已通过。在后面的列表示例中,我省略了这一点
    //并且具有不同参数的调用的保存方式也不同
    ()=>“p”
    );
    我保证([
    //这将使用一个永久缓存,其中包含对函数的所有调用
    //保存在同一个键下,因此testPromise函数
    //只称为onc
    
    import ...
    
    export default function Gallery() {
    
      return(
        <>
    
          <GalleryTabs />
          <GalleryText />
    
          <div className="gallery-images-container">
            <Thumbnail />  -----> Thumbnail should be rendered here but not Carousel ( FetchImages here adds unnecessary complexity )   
          </div>
    
        </>
      )  
    }