代码之家  ›  专栏  ›  技术社区  ›  grazdev

如何调度多个动作创建者(React+Redux+服务器端渲染)

  •  6
  • grazdev  · 技术社区  · 6 年前

    我一直在学习一门关于如何使用React和Redux构建服务器端渲染应用程序的很好的课程,但我现在遇到的情况是,这门课程没有涵盖,我自己也无法理解。

    请考虑以下组件(除了底部的导出部分外,它非常基本):

    class HomePage extends React.Component {
    
        componentDidMount() {       
            this.props.fetchHomePageData();
        }   
    
        handleLoadMoreClick() {
            this.props.fetchNextHomePagePosts();
        }   
    
        render() {
    
            const posts = this.props.posts.homepagePosts; 
            const featuredProject = this.props.posts.featuredProject; 
            const featuredNews = this.props.posts.featuredNews; 
            const banner = this.props.posts.banner; 
            const data = ( posts && featuredProject && featuredNews && banner ); 
    
            if( data == undefined ) {
                return <Loading />; 
            }
    
            return(
                <div>
                    <FeaturedProject featuredProject={ featuredProject } />
                    <FeaturedNews featuredNews={ featuredNews } />
                    <Banner banner={ banner } />                
                    <PostsList posts={ posts } heading="Recently on FotoRoom" hasSelect={ true } />
                    <LoadMoreBtn onClick={ this.handleLoadMoreClick.bind( this ) } />               
                </div>
            ); 
    
        }
    
    }
    
    function mapStateToProps( { posts } ) {
        return { posts }
    }
    
    export default {
        component: connect( mapStateToProps, { fetchHomePageData, fetchNextHomePagePosts } )( HomePage ),
        loadData: ( { dispatch } ) => dispatch( fetchHomePageData() )
    };
    

    以上操作很好:loadData函数发出API请求以获取一些数据,这些数据通过mapStateToProps函数馈送到组件中。但如果我想在同一个loadData函数中解雇多个动作创建者,该怎么办?唯一可行的是,如果我这样写函数:

    function loadData( store ) {
        store.dispatch( fetchFeaturedNews() );
        return store.dispatch( fetchHomePageData() );
    }
    
    export default {
        component: connect( mapStateToProps, { fetchHomePageData, fetchNextHomePagePosts } )( HomePage ),
        loadData: loadData
    };
    

    但这并不好,因为我需要返回所有数据。。。请记住,导出的组件最终将处于以下路由配置中:

    const Routes = [
        {
            ...App, 
            routes: [
                {
                    ...HomePage, // Here it is!
                    path: '/', 
                    exact: true
                },
                {
                    ...LoginPage, 
                    path: '/login'
                },              
                {
                    ...SinglePostPage, 
                    path: '/:slug'
                },
                {
                    ...ArchivePage, 
                    path: '/tag/:tag'
                },                                      
            ]
        }
    ];
    

    以下是在某条路线需要组件时如何使用loadData函数:

    app.get( '*', ( req, res ) => {
    
        const store = createStore( req ); 
    
        const fetchedAuthCookie = req.universalCookies.get( authCookie ); 
    
        const promises = matchRoutes( Routes, req.path ).map( ( { route } ) => {
            return route.loadData ? route.loadData( store, req.path, fetchedAuthCookie ) : null;
        }).map( promise => {
            if( promise ) {
                return new Promise( ( resolve, reject ) => {
                    promise.then( resolve ).catch( resolve ); 
                }); 
            }
        });
    
        ...
    
    }
    

    此外,这里还有一个动作创建者触发的动作示例。他们都承诺:

    export const fetchHomePageData = () => async ( dispatch, getState, api ) => {
    
        const posts = await api.get( allPostsEP );
    
        dispatch({
            type: 'FETCH_POSTS_LIST', 
            payload: posts
        });             
    
    }
    

    和减速器:

    export default ( state = {}, action ) => {
        switch( action.type ) {
            case 'FETCH_POSTS_LIST':
                return {
                    ...state, 
                    homepagePosts: action.payload.data 
                }                                       
            default: 
                return state; 
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Tomasz Mularczyk    6 年前

    因此,你的行动回报了一个承诺,你在问,你如何才能回报不止一个承诺。使用 Promise.all :

    function loadData({ dispatch }) {
      return Promise.all([
        dispatch( fetchFeaturedNews() ),
        dispatch( fetchHomePageData() ),
      ]);
    }
    

    但是记住这个承诺。当所有的承诺都得到解决时,一切都会得到解决,它将返回一个 大堆 价值观:

    function loadData({ dispatch }) {
      return Promise.all([
        dispatch( fetchFeaturedNews() ),
        dispatch( fetchHomePageData() ),
      ]).then(listOfResults => {
        console.log(Array.isArray(listOfResults)); // "true"
        console.log(listOfResults.length); // 2
      });
    }
    

    因此,您可能希望以不同的方式处理它。