Redux&反应路由器:梳理调度和导航(history.push)

时间:2017-12-24 03:31:21

标签: javascript redux react-router react-redux

关于如何将React Router的history.push('/route')Redux一起使用,我有点无能为力。

换句话说,如果您使用Redux的mapDispatchToProps连接组件,那么如何在调度某个操作后放置应该被触发的history.push('/route')

为了澄清这个问题,这里有一个我的实验片段......

class PostContainer extends React.Component {

    handleSubmit(data) {
        return this.props.addPost(data);
    }

    render() {
        return (<Post onSubmit={data=> this.handleSubmit(data)}/>);
    }
}

const mapDispatchToProps = (dispatch) => {
    return {    
        addPost: (data) => {
            dispatch(addPost(data)).data.then((result) => {
                dispatch(addPostFulfilled(result.data));

                //How do you call the following function?
                this.props.history.push('/posts')
            }).catch((error) => {
                dispatch(addPostRejected());
            });
        },      
    }
}

export default connect(null, mapDispatchToProps)(PostContainer);

正如您所看到的,只要帖子通过addPostFulfilled添加到Redux的状态,页面就需要通过history.push移至/posts

根据Redux的文档,容器用于更新状态(以及获取数据)。所以,愚蠢的组件不应该像history.push那样放置。

比上面的代码更好的方法是什么?

任何建议都将受到赞赏。

3 个答案:

答案 0 :(得分:3)

您可以使用用户react-router-redux(需要初始设置)并从动作创建者发送您的操作

import { push } from 'react-router-redux'
    class PostContainer extends React.Component {

    handleSubmit(data) {
        return this.props.addPost(data);
    }

    render() {
        return (
            <div>
                <Post onSubmit={data=> this.handleSubmit(data)}/>
            </div>
        );
    }
}

const mapDispatchToProps = (dispatch) => {
    return {    
        addPost: (data) => {
            dispatch(addPost(data)).data.then((result) => {
                dispatch(addPostFulfilled(result.data));

                //How do you call the following function?
                dispatch(push('/posts'));
            }).catch((error) => {
                dispatch(addPostRejected());
            });
        },      
    }
}
export default connect(null, mapDispatchToProps)(PostContainer);

或者只是将push作为“完成回调”传递。

class PostContainer extends React.Component {

    handleSubmit(data, done) {
        return this.props.addPost(data, done);
    }

    render() {
        const { push } = this.props.history;
        return (
            <div>
                <Post onSubmit={data=> this.handleSubmit(data, push)}/>
            </div>
        );
    }
}

const mapDispatchToProps = (dispatch) => {
    return {    
        addPost: (data, done) => {
            dispatch(addPost(data)).data.then((result) => {
                dispatch(addPostFulfilled(result.data));

                //How do you call the following function?
                done('/posts')
            }).catch((error) => {
                dispatch(addPostRejected());
            });
        },      
    }
}

export default connect(null, mapDispatchToProps)(PostContainer);

答案 1 :(得分:0)

恕我直言,你甚至可以从你的愚蠢组成部分做const mapDispatchToProps = (dispatch) => { return { addPost: (data) => { dispatch(addPost(data)).data.then((result) => { dispatch(addPostFulfilled(result.data)); <!-- removed from here --> }).catch((error) => { dispatch(addPostRejected()); }); }, } } ,即

addPostFulFilled

完成this.history.push('/route')数据后,您可以选择在组件中执行props。您可以执行componentWillReceiveProps更新时调用的任何生命周期方法。 也许,将其添加到class PostContainer extends React.Component { componentWillReceiveProps(nextProps){ /*Added here*/ if(nextProps.someFlag){ this.props.history.push('/someRoute'); }}

store

请注意,上述内容仅适用于

  1. 您可以通过react-router-4跟踪位置更改。(Read More
  2. 您正在使用withRouter,在这种情况下,您将使用PostContainer包裹您的连接,这将使历史对象在shouldComponentUpdate中作为道具出现。
  3. 应注意防止不必要的重新渲染并在react-router-redux中编写必要的逻辑。
  4. 如果上述内容听起来像是一大堆乱码,您可以随时使用push的{​​{1}} API,以便在浏览器历史记录中推送新条目。您可以在您选择的任何地方导入,只需推送新路线。

    详细信息可以在react-router-redux github pages中看到并引用文档

      

    push和replace都包含一个位置描述符,它可以是一个   描述URL的对象或纯字符串URL。这些动作创作者   也可以作为routerActions在一个对象中使用   在使用Redux的bindActionCreators()时可以方便地使用。

    因此,请直接使用mapDispatchToProps中的history.push(),或将其作为道具传递给PostContainer反应组件中使用。

答案 2 :(得分:0)

更清洁的方法可能是使用React Router的<Redirect>

class PostContainer extends React.Component {
    render() {
        if (userJustAddedAPostRightNow === true) {
             return <Redirect to='/posts' />
        }
        return (
            <div>
                <Post onSubmit={addPost}/>
            </div>
        );
    }
}
export default connect(null, { addPost })(PostContainer);

addPost如果成功将触发状态更改。它应该将userJustAddedAPostRightNow更改为true,以便将您重定向到帖子的页面。

要避免所有这些嵌套的回调,可以遵循Nir Kaufman's approach并处理中间件中的逻辑:

//src/middlewares/post.js
export const newPost = ({dispatch}) => next => action => {
  next(action);

  if (action.type === ADD_POST) {
    dispatch(apiRequest('POST', action.URL, null, ADD_POST_SUCCESS, ADD_POST_ERROR));
    dispatch(showSpinner());
  }
};

然后,如果成功,ADD_POST_SUCCESS动作将通过减速器更改userJustAddedAPostRightNow的值。