React Router V4正在更新URL,但不刷新页面(React,Redux)

11

我正在尝试使用React-Router V4为我的应用程序添加路由,但它根本不起作用。基本上,我正试图使用history.push编程方式更改路由,这会更新浏览器URL,但不会在实际应用程序内更改任何内容。

注意:我正在使用redux。

这个问题上唯一有答案的问题是:

React history.push() is updating url but not navigating to it in browser

然而,我已经尝试了上述问题的答案,但对我没有用。

以下是重要的代码段:

顶层文件(index.js)

...
ReactDOM.render(
    <BrowserRouter>
        <Provider store={store}>
            <App/>
        </Provider>
    </BrowserRouter>
    , document.getElementById('root'));
...

包含路由的组件

...
export default function ContentRouter() {
    return <div className="content">
        <Route exact path="/dashboard" component={TmpDashboard}/>
        <Route exact path="/" component={() => {
            return <h1>Home</h1>
        }}/>
    </div>
}

组件推送路由

...
this.handleGroupClick = (group) => {
    this.props.history.push(`/groups/${group}`);
    this.props.onOpenChange(false);
};
...
export default withRouter(connect(mapStateToProps, mapDispatchToProps(DrawerConnector))


这里有一个:this.props.history.push https://dev59.com/PF0Z5IYBdhLWcg3wxCuQ - admcfajn
@admcfajn 那就是我现在正在尝试的一个。 - user5182794
我在ContentRouter中没有看到DrawerConnector。它在哪里被使用?它是否嵌套在这些组件之一中?我发现在我的顶层组件上使用withRouter并在其中使用<Route component="fooComponent" />很有用。对于他们的嵌套组件,我将history作为props传递。希望这样说得清楚。 - Hossein
@Hossein DrawerConnector需要嵌套在路由内部吗?我以为它只需要嵌套在路由器内部。 - user5182794
是的,@AJC。我曾经遇到过这个问题,我的侧边栏在<BrowserHistory>中,但没有包装在更高级别的路由器中,即使历史记录被传递给它,它也无法工作。 - Hossein
@Hossein,您能否添加一个解释并附带一些示例代码的答案?非常感谢! - user5182794
2个回答

14

在完全错误的地方搜索了很多之后,我找到了问题所在。缺乏更新是由Redux引起的。

每当一个组件被包装在connect中时,它会导致更新被阻止,视图不会更新。

解决方案在这里提到:

https://github.com/ReactTraining/react-router/issues/4671#issuecomment-285320076

基本上,每个带有 Route 或 React-Router 的组件都必须用 withRouter 包装。

编辑:只有使用 connect 的顶级组件应该被包装在 withRouter 中。请注意,这可能会导致性能问题。

编辑:我解决增加的耦合的方法是创建一个专门处理路由的组件。这样,我只需要将该组件和带有 Router 的组件包装起来即可。


虽然那样做可以起作用,但会相当烦扰。你不应该把每个组件都包装在 WithRouter 中。我建议你看一下我的答案,这是一个耦合度更低的版本。无论如何,很高兴你找到了解决方案! - Hossein

0
这是一个可行的设置:
主应用程序:
class App extends React.Component {

    render() {
        return (
            <BrowserRouter>
                <div>
                   /* this is a common component and happens to need to redirect */
                   <Route component={CommonComponentThatPushesToHistory} />
                   <div id="body">
                       /* I usually place this switch in a separate Routes file */
                       <Switch>
                           <Route exact path="FooRoute" component={FooPage}/>
                           <Route exact path="BarRoute" component={BarPage}/>
                        </Switch>
                   </div>
                   /* another common component which does not push to history */
                   <Footer />
                </div>
            </BrowserRouter>
        );
    }
}

export default withRouter(App);

推送历史记录的常见组件

class CommonComponentThatPushesToHistory extends React.Component{
    render(){
        return(
            <button type="button" 
                onClick={() => {this.props.history.push('some-page');}}>
                Click to get redirected</button>
        );
    }
}

FooPage 可能有一个子组件,它会推送到历史记录:

class FooPage extends React.Component{
    render(){
        return(
            <MyChild history={this.props.history} />
        );
    }
}

然后,MyChild组件可以像CommonComponentThatPushesToHistory一样将其推送到历史记录中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接