ReactJs / Redux不变违规:无法找到“存储”在“Connect(LoginContainer)”的上下文或道具中 [英] ReactJs/Redux Invariant Violation: Could not find "store" in either the context or props of "Connect(LoginContainer)"

查看:760
本文介绍了ReactJs / Redux不变违规:无法找到“存储”在“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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆