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

How to dispatch multiple action creators (React + Redux + Server-side rendering)

提问人:grazdev 提问时间:3/29/2018 最后编辑:Tomasz Mularczykgrazdev 更新时间:3/30/2018 访问量:1505

问:

我一直在学习一门关于如何使用 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; 
    }
}
JavaScript ReactJS Redux 服务器端渲染

评论

0赞 Tomasz Mularczyk 3/29/2018
我可能遗漏了一些东西,但你不能直接返回数组吗?您能展示一下以后如何使用您的函数吗?loadData
0赞 grazdev 3/29/2018
@TomaszMularczyk 嗨,我已经更新了我的答案。感谢您的观看!
0赞 Mayank Shukla 3/30/2018
@grazianodev你能解释一下,但这不是很好,因为我需要返回所有数据?“要返回的数据”是什么意思?
0赞 grazdev 3/30/2018
@MayankShukla 好吧,现在 loadData 函数只返回 ;我想要的是 loadData 函数同时返回该函数和 .换句话说,我希望它返回两组数据,而不仅仅是一组数据,这样它们就可以在我问题最底部的函数中映射。将它们组合成一个@TomasMularczyk建议的数组听起来不错,但我似乎无法让它工作......fetchHomePageData()fetchFeaturedNews()app.get( ... )
0赞 Tomasz Mularczyk 3/30/2018
可以显示 fetch 的实现...他们会返回 Promise 吗?

答:

2赞 Tomasz Mularczyk 3/29/2018 #1

因此,你的操作会返回一个 Promise,而你正在问你如何才能返回多个 Promise。使用 Promise.all

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

但。。。请记住,当所有 Promise 都解析时,Promise.all 将解析,并且它将返回一个值数组

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

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

评论

0赞 grazdev 3/30/2018
正是我想要的。非常感谢!
0赞 Shivansh Jagga 1/25/2019
谢谢。但是如何在 mapStatetoProps 函数中处理这个问题,我只得到了第二个请求的结果。