ReactJs / Redux不变违规:无法找到“存储”在“Connect(LoginContainer)”的上下文或道具中 [英] ReactJs/Redux Invariant Violation: Could not find "store" in either the context or props of "Connect(LoginContainer)"
问题描述
我不知道为什么我收到此错误,当我从 redux
添加 connect
到我的登录时发生了组件,所以我可以连接我的商店
。
Not sure why I'm getting this error, it happened when I added connect
from redux
to my Login component, so I could connect my store
.
FAIL src / components / auth /Login.test.js
FAIL src/components/auth/Login.test.js
●测试套件无法运行
不变违规:无法找到商店在Connect(LoginContainer)的上下文或道具中。将根组件包装在< Provider>
中,或者将store显式传递给Connect(LoginContainer)。
Invariant Violation: Could not find "store" in either the context or props of "Connect(LoginContainer)". Either wrap the root component in a <Provider>
, or explicitly pass "store" as a prop to "Connect(LoginContainer)".
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from "react-redux"
import { createCommonStore } from "./store";
import App from './App'
import css from './manage2.scss'
const store = createCommonStore();
const element = document.getElementById('manage2');
console.log("Index.js Default store", store.getState());
ReactDOM.render(
<Provider store={store}> // <-- store added here
<App />
</Provider>, element);
store.js
store.js
import React from "react"
import { applyMiddleware, combineReducers, compose, createStore} from "redux"
import thunk from "redux-thunk"
import { userReducer } from "./reducers/UserReducer"
import { authReducer } from "./reducers/AuthReducer"
export const createCommonStore = (trackStore=false) => {
const reducers = combineReducers({
user: userReducer,
user: authReducer
});
//noinspection JSUnresolvedVariable
const store = createStore(reducers,
compose(
applyMiddleware(thunk),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
);
if (trackStore) {
store.subscribe((() => {
console.log(" store changed", store.getState());
}));
}
return store;
};
App.js
App.js
import React from 'react'
import { BrowserRouter as Router } from 'react-router-dom'
import Routes from './components/Routes'
const supportsHistory = "pushState" in window.history
export default class App extends React.Component {
render() {
return (
<Router forceRefresh={!supportsHistory}>
<Routes />
</Router>
);
}
}
Routes.js
Routes.js
import React from 'react'
import { Route, Switch } from 'react-router-dom'
import LoginContainer from './auth/Login'
import Dashboard from './Dashboard'
import NoMatch from './NoMatch'
const Routes = () => {
return (
<Switch>
<Route exact={ true } path="/" component={ LoginContainer }/>
<Route path="/dashboard" component={ Dashboard }/>
<Route component={ NoMatch } />
</Switch>
);
}
export default Routes
最后Login.js(为简洁而删除的代码
Finally Login.js (code removed for brevity
import React from 'react'
import { connect } from "react-redux"
import { bindActionCreators } from 'redux';
import { setCurrentUser } from '../../actions/authActions'
import * as api from '../../services/api'
const mapDispatchToProps = (dispatch) => {
console.log('mapDispatchToProps', dispatch);
return {
setUser: (user) => {
bindActionCreators(setCurrentUser(user), dispatch)
}
}
}
class LoginContainer extends React.Component {
constructor(props) {
super(props)
this.state = {};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
}
handleSubmit(e) {
}
render() {
return (
<div className="app-bg">
...
</div>
)
}
}
export default connect(null, mapDispatchToProps)(LoginContainer);
Login.test
Login.test
import React from 'react'
import ReactTestUtils from 'react-dom/test-utils'
import { mount, shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
import { missingLogin } from '../../consts/errors'
import Login from './Login'
import Notification from '../common/Notification'
const loginComponent = shallow(<Login />);
const fakeEvent = { preventDefault: () => '' };
describe('<Login /> component', () => {
it('should render', () => {
const tree = toJson(loginComponent);
expect(tree).toMatchSnapshot();
});
it('should render the Notification component if state.error is true', () => {
loginComponent.setState({ error: true });
expect(loginComponent.find(Notification).length).toBe(1);
});
});
describe('User Login', () => {
it('should fail if no credentials are provided', () => {
expect(loginComponent.find('.form-login').length).toBe(1);
loginComponent.find('.form-login').simulate('submit', fakeEvent);
expect(loginComponent.find(Notification).length).toBe(1);
const notificationComponent = shallow(<Notification message={ missingLogin }/>);
expect(notificationComponent.text()).toEqual('Please fill out both username and password.');
});
it('input fields should be filled correctly', () => {
const credentials = { username: 'leongaban', password: 'testpass' };
expect(loginComponent.find('#input-auth-username').length).toBe(1);
const usernameInput = loginComponent.find('#input-auth-username');
usernameInput.value = credentials.username;
expect(usernameInput.value).toBe('leongaban');
const passwordInput = loginComponent.find('#input-auth-password');
passwordInput.value = credentials.password;
expect(passwordInput.value).toBe('testpass');
});
});
这里看错了什么?
推荐答案
Redux建议导出未连接的组件以进行单元测试。查看他们的文档。
Redux recommends exporting the unconnected component for unit tests. See their docs.
在login.js中:
In login.js:
// Named export for tests
export class LoginContainer extends React.Component {
}
// Default export
export default connect(null, mapDispatchToProps)(LoginContainer);
在你的测试中:
// Import the named export, which has not gone through the connect function
import { LoginContainer as Login } from './Login';
然后,您可以直接在组件上指定任何来自商店的道具。
You can then specify any props that would have come from the store directly on the component.
这篇关于ReactJs / Redux不变违规:无法找到“存储”在“Connect(LoginContainer)”的上下文或道具中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!