在上下文提供程序中使用withRouter会导致错误:“不变失败:您不应在<router>之外使用<route>”

时间:2019-05-15 08:14:31

标签: reactjs react-router react-context

我正在应用中生成路由器组件:

render() {
        return (
            <div className="App container-fluid">
                <CharacterProvider>
                    <Router>
                        <div>
                            <Link to="/new">New Character</Link>
                            <Link to="/load">Load Character</Link>
                            <Route path="/new" component={NewCharacter} />
                            <Route path="/load" component={CharacterSheet} />
                            <Route path="/edit" component={EditCharacter} />
                            <Route exact path="/" component={MenuImages} />
                        </div>
                    </Router>
                </CharacterProvider>
            </div>
        );
    }

但是我需要将历史记录推送到提供程序组件中包含的功能中:

import React, {Component} from "react";
import {withRouter} from "react-router-dom";
import CharacterDataService from "../service/CharacterDataService";

const CharacterContext = React.createContext()
const CharacterConsumer = CharacterContext.Consumer

class CharacterProvider extends Component {
    constructor(props) {
        super(props);

        this.state = {
            ...
            getCharacter: this.getCharacter,
        }
    }

    getCharacter = (id) => {
        console.log("Getting character...")
        CharacterDataService.getCharacterById(id)
            .then(
                response => {
                    console.log(response);
                    this.setState({
                        ...
                    });
                }
            );
        this.props.history.push('/load');
    }


    render() {
        return (
            <CharacterContext.Provider
                value={this.state}>
               {
                   this.props.children
               }
            </CharacterContext.Provider>
        )
    }
}

export { CharacterContext, CharacterConsumer}
export default withRouter(CharacterProvider)

这样做会导致此堆栈跟踪出错:

tiny-invariant.esm.js:12 Uncaught Error: Invariant failed: You should not use <Route> outside a <Router>
    at invariant (tiny-invariant.esm.js:12)
    at react-router.js:409
    at updateContextConsumer (react-dom.development.js:16085)
    at beginWork (react-dom.development.js:16306)
    at performUnitOfWork (react-dom.development.js:20285)
    at workLoop (react-dom.development.js:20326)
    at HTMLUnknownElement.callCallback (react-dom.development.js:147)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:196)
    at invokeGuardedCallback (react-dom.development.js:250)
    at replayUnitOfWork (react-dom.development.js:19509)
    at renderRoot (react-dom.development.js:20439)
    at performWorkOnRoot (react-dom.development.js:21363)
    at performWork (react-dom.development.js:21273)
    at performSyncWork (react-dom.development.js:21247)
    at requestWork (react-dom.development.js:21102)
    at scheduleWork (react-dom.development.js:20915)
    at scheduleRootUpdate (react-dom.development.js:21610)
    at updateContainerAtExpirationTime (react-dom.development.js:21636)
    at updateContainer (react-dom.development.js:21704)
    at ReactRoot.push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render (react-dom.development.js:22017)
    at react-dom.development.js:22169
    at unbatchedUpdates (react-dom.development.js:21492)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:22165)
    at Object.render (react-dom.development.js:22240)
    at Module../src/index.js (index.js:8)
    at __webpack_require__ (bootstrap:781)
    at fn (bootstrap:149)
    at Object.0 (serviceWorker.js:135)
    at __webpack_require__ (bootstrap:781)
    at checkDeferredModules (bootstrap:45)
    at Array.webpackJsonpCallback [as push] (bootstrap:32)
    at main.chunk.js:1
invariant @ tiny-invariant.esm.js:12
(anonymous) @ react-router.js:409
updateContextConsumer @ react-dom.development.js:16085
beginWork @ react-dom.development.js:16306
performUnitOfWork @ react-dom.development.js:20285
workLoop @ react-dom.development.js:20326
callCallback @ react-dom.development.js:147
invokeGuardedCallbackDev @ react-dom.development.js:196
invokeGuardedCallback @ react-dom.development.js:250
replayUnitOfWork @ react-dom.development.js:19509
renderRoot @ react-dom.development.js:20439
performWorkOnRoot @ react-dom.development.js:21363
performWork @ react-dom.development.js:21273
performSyncWork @ react-dom.development.js:21247
requestWork @ react-dom.development.js:21102
scheduleWork @ react-dom.development.js:20915
scheduleRootUpdate @ react-dom.development.js:21610
updateContainerAtExpirationTime @ react-dom.development.js:21636
updateContainer @ react-dom.development.js:21704
push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @ react-dom.development.js:22017
(anonymous) @ react-dom.development.js:22169
unbatchedUpdates @ react-dom.development.js:21492
legacyRenderSubtreeIntoContainer @ react-dom.development.js:22165
render @ react-dom.development.js:22240
./src/index.js @ index.js:8
__webpack_require__ @ bootstrap:781
fn @ bootstrap:149
0 @ serviceWorker.js:135
__webpack_require__ @ bootstrap:781
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous) @ main.chunk.js:1
Show 2 more frames
index.js:1437 The above error occurred in the <Context.Consumer> component:
    in Route (created by withRouter(CharacterProvider))
    in withRouter(CharacterProvider) (at App.js:41)
    in div (at App.js:40)
    in App (at src/index.js:8)

我正在做的是使用更改提供者状态的函数-但是,由于该函数用于onClick动作中,因此我还需要根据触发该动作的元素来更改路由。提供者的类不在路由器的结构之外,因此我需要一种在提供者组件中启用历史记录的方法。有比使用withRouter更好的方法来解决问题吗?我怎么用错了?

1 个答案:

答案 0 :(得分:1)

由于您的Router不是withRouter(CharacterProvider)的父级组件(这是react-router的要求),因此会出现错误。

尝试更改RouterCharacterProvider组件的顺序:

<Router>
    <CharacterProvider>
        { /* The rest of your components */ }
    </CharacterProvider>
</Router>