【发布时间】:2019-07-25 06:10:41
【问题描述】:
我创建了这个 RootContext 来处理我的小型 React Hooks 应用程序的身份验证。除了使用 Enzyme 的 shallow 和 mount 出现奇怪的错误外,一切都按预期工作。
我正在尝试这样测试:
const wrapper = mount(<Login />)
索引:
import RootContext from './RootContext'
function Root() {
return (
<RootContext>
<App />
</RootContext>
)
}
ReactDOM.render(<Root/>, document.getElementById('root'));
根上下文:
import React, { useEffect, useState } from 'react'
export const RootContext = React.createContext()
export default ({ children }) => {
const auth = window.localStorage.getItem('authenticated') || 'false'
const cred = window.localStorage.getItem('credentials') || null
const [authenticated, setAuthenticated] = useState(auth)
const [credentials, setCredentials] = useState(cred)
useEffect(
() => {
window.localStorage.setItem('authenticated', authenticated)
window.localStorage.setItem('credentials', credentials)
},
[authenticated, credentials]
)
const defaultContext = {
authenticated,
setAuthenticated,
credentials,
setCredentials
}
return (
<RootContext.Provider value={defaultContext}>
{children}
</RootContext.Provider>
)
}
登录、注销和注册都使用了导致此问题的useAuthenticate 挂钩。 BmiForm 组件工作正常。
import AuthenticatedRoute from './AuthenticatedRoute'
export default function App() {
return (
<Router>
<Header />
<Switch>
<Container>
<Row>
<Col md={{ span: 4, offset: 4 }}>
<AuthenticatedRoute exact path="/" component={BmiForm} />
<Route exact path="/login" component={ Login } />
<Route exact path="/logout" component={ Logout } />
<Route exact path="/register" component={ Register } />
</Col>
</Row>
</Container>
</Switch>
</Router>
)
}
导致问题的useAuthenticate 钩子:
import useReactRouter from 'use-react-router';
import { RootContext } from './../RootContext'
export default function useAuthenticate() {
const { history } = useReactRouter()
const {
authenticated,
setAuthenticated,
credentials,
setCredentials
} = useContext(RootContext);
将useAuthenticate 钩子添加到 BmiForm 会导致其测试以同样的方式失败。
import useAuthenticate from './custom/useAuthenticate'
export default function BmiForm(props) {
const { credentials, setAuthenticated } = useAuthenticate()
我得到的第一个错误:
TypeError: Cannot read property 'authenticated' of undefined
5 | export default function useAuthenticate() {
6 | const {
> 7 | authenticated,
| ^
8 | setAuthenticated,
9 | credentials,
10 | setCredentials
stacktrace 的第二个错误:
use-react-router may only be used within a react-router context.
4 |
5 | export default function useAuthenticate() {
> 6 | const { history } = useReactRouter()
| ^
7 | const {
8 | authenticated,
9 | setAuthenticated,
at useRouter (node_modules/use-react-router/src/use-react-router.ts:20:11)
at useAuthenticate (src/custom/useAuthenticate.js:6:23)
at BmiForm (src/BmiForm.js:15:45)
at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:12839:18)
at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:14816:13)
at beginWork (node_modules/react-dom/cjs/react-dom.development.js:15421:16)
at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:19108:12)
at workLoop (node_modules/react-dom/cjs/react-dom.development.js:19148:24)
at renderRoot (node_modules/react-dom/cjs/react-dom.development.js:19231:7)
at performWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:20138:7)
at performWork (node_modules/react-dom/cjs/react-dom.development.js:20050:7)
at performSyncWork (node_modules/react-dom/cjs/react-dom.development.js:20024:3)
at requestWork (node_modules/react-dom/cjs/react-dom.development.js:19893:5)
at scheduleWork (node_modules/react-dom/cjs/react-dom.development.js:19707:5)
at scheduleRootUpdate (node_modules/react-dom/cjs/react-dom.development.js:20368:3)
at updateContainerAtExpirationTime (node_modules/react-dom/cjs/react-dom.development.js:20396:10)
at updateContainer (node_modules/react-dom/cjs/react-dom.development.js:20453:10)
at ReactRoot.Object.<anonymous>.ReactRoot.render (node_modules/react-dom/cjs/react-dom.development.js:20749:3)
at node_modules/react-dom/cjs/react-dom.development.js:20886:14
at unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:20255:10)
at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:20882:5)
at Object.render (node_modules/react-dom/cjs/react-dom.development.js:20951:12)
at Object.render (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:382:114)
at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:134:16)
at mount (node_modules/enzyme/build/mount.js:21:10)
at test (src/test/bmi_calculator.step.test.js:22:21)
at defineScenarioFunction (node_modules/jest-cucumber/src/feature-definition-creation.ts:155:9)
at test (src/test/bmi_calculator.step.test.js:20:3)
at Suite.<anonymous> (node_modules/jest-cucumber/src/feature-definition-creation.ts:279:9)
at defineFeature (node_modules/jest-cucumber/src/feature-definition-creation.ts:278:5)
at Object.<anonymous> (src/test/bmi_calculator.step.test.js:19:1)
我尝试了涉及 Enzyme 的 setContext 的各种解决方案。但不确定这是否与上下文或react-router 或两者有关。
【问题讨论】:
-
你试过
mount(<BrowserRouter><Login /></BrowserRouter),其中BrowserRouter是从react-router导入的吗?
标签: reactjs enzyme react-router-v4 react-hooks react-context