【问题标题】:Invariant Violation: Could not find "store" in either the context or props of "Connect(App)"不变违规:在“Connect(App)”的上下文或道具中找不到“store”
【发布时间】:2018-10-08 08:15:09
【问题描述】:

您好,我正在尝试在 react-native 应用程序中使用 redux,但我收到了标题中提到的错误,特别是 Invariant Violation: Could not find "store" in either the context or props of "Connect(App)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(App)"。我不确定是什么问题,虽然我关注了类似的线程,但到目前为止没有任何效果。

下面是我的 App.js 源码

import React, { Component } from 'react';
import { Provider, connect } from 'react-redux';
import { Platform, StyleSheet, Text, View } from 'react-native';
import * as utils from './src/utils';
import store from './src/store';

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

class App extends React.Component {

    constructor(...args) {
        super(...args);
    }

    login({ username, password }) {

        let requestData = new FormData();

        requestData.append('username', username);
        requestData.append('password', password);

        console.log('[Login]: Attempt');
        console.log(JSON.stringify(requestData, null, 4));

        fetch('https://my-api.lab/user/login', {
            method: 'POST',
            body: requestData
        }).then(res => res.json()).then((json) => {

            console.log('[Login]: Response');
            console.log(JSON.stringify(json, null, 4));

            if (json.authenticated) {

                console.log('[Login]: Success');

                this.props.userLoginSuccess(json);

            } else {
                console.log('[Login]: Failure');
            }

        }).catch((err) => {

            console.log('[Login]: error');
            console.log(JSON.stringify(err, null, 4));

        });

    }

    componentDidMount() {

        console.log('App mounted!');

        this.login({
            username: 'asdf',
            password: 'asdf'
        });

    }

    render() {

        let username = Object.keys(this.props.user).length ? this.props.user.data.post.username : '';

        return (

            <Provider store={store}>

                <View style={styles.container}>
                    <Text style={styles.welcome}>
                        Welcome {username} to React Native!
                    </Text>
                </View>

            </Provider>

        );
    }
}

const mapStateToProps = (state) => {
    return {
        user: state.userReducer
    }
}

const mapDispatchToProps = (dispatch) => {

    return {

        userLoginSuccess: (user) => {

            dispatch({
                type: 'USER_LOGIN_SUCCESS',
                payload: user
            })

        },

        userLoginFailure: (user) => {

        }

    }

}

export default connect(mapStateToProps, mapDispatchToProps)(App);

这也是我的 index.js 文件

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('pushNotificationsNative', () => App);

商店

import { createStore } from 'redux';
import rootReducer from '../reducers/index.js';

const store = createStore(
    rootReducer
);

export default store;

最后是一个简单的 reducer

import deepExtend from 'deep-extend';

const initialState = {};

const userReducer = (state = initialState, action) => {

    switch (action.type) {

        case 'USER_LOGIN_SUCCESS': {
            return deepExtend({}, state, action.payload);
        }

        default: {
            return deepExtend({}, state);
        }

    }

}

export default userReducer;

【问题讨论】:

  • 我还在看其余的代码,但你为什么要在构造函数中使用展开?您实际上甚至不需要这里的构造函数,因为您没有在其中做任何事情。仅当您在构建类时确实需要做某事时才这样做。

标签: reactjs react-native redux react-redux


【解决方案1】:

您正在尝试访问 App 组件中的商店,而您的 Provider 位于其中。因此,App 并没有真正从上下文中获取商店。您需要将 App 与 Provider 类似

class App extends React.Component {

    constructor(...args) {
        super(...args);
    }

    login({ username, password }) {

        let requestData = new FormData();

        requestData.append('username', username);
        requestData.append('password', password);

        console.log('[Login]: Attempt');
        console.log(JSON.stringify(requestData, null, 4));

        fetch('https://my-api.lab/user/login', {
            method: 'POST',
            body: requestData
        }).then(res => res.json()).then((json) => {

            console.log('[Login]: Response');
            console.log(JSON.stringify(json, null, 4));

            if (json.authenticated) {

                console.log('[Login]: Success');

                this.props.userLoginSuccess(json);

            } else {
                console.log('[Login]: Failure');
            }

        }).catch((err) => {

            console.log('[Login]: error');
            console.log(JSON.stringify(err, null, 4));

        });

    }

    componentDidMount() {

        console.log('App mounted!');

        this.login({
            username: 'asdf',
            password: 'asdf'
        });

    }

    render() {

        let username = Object.keys(this.props.user).length ? this.props.user.data.post.username : '';

        return (
                <View style={styles.container}>
                    <Text style={styles.welcome}>
                        Welcome {username} to React Native!
                    </Text>
                </View>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        user: state.userReducer
    }
}

const mapDispatchToProps = (dispatch) => {

    return {

        userLoginSuccess: (user) => {

            dispatch({
                type: 'USER_LOGIN_SUCCESS',
                payload: user
            })

        },

        userLoginFailure: (user) => {

        }

    }

}

const ConnectedApp = connect(mapStateToProps, mapDispatchToProps)(App);

export default const Root = () => {
    <Provider store={store}><ConnectedApp/></Provider>
}

【讨论】:

    【解决方案2】:

    您已将 App 包装在 connect() 方法中,但要在 App 中实例化 &lt;Provider&gt; 组件。我的预感是,此时没有store 用于连接访问并提供给App。尝试删除连接语句,看看是否能解决您的问题。

    您的代码依赖于来自商店的数据,我暂时将其注释掉,看看上述解决方案是否有效。如果是这样,让应用程序只是一个简单的组件,它支持商店并将用于登录和检查用户的代码移动到一个新组件。

    【讨论】:

      【解决方案3】:

      Provider 必须包装一个更高级别的组件。 底层组件,或嵌套组件导入到提供者的组件中,应该具有连接功能。

      顶层(index.js):

      AppRegistry.registerComponent(appName, () => App);
      

      高层组件(app.js):

      const store = createStore(reducers);
      const App = () => {
          return <Provider store={store}>
              <UI/>
          </Provider>;
      };
      export default App;
      

      低级/嵌套(ui.js)

      const UI = () => {
      return <View><Text>Hello</Text></View>;
      };
      export default connect()(UI);
      

      这个问题是 react-native 特有的,因为在 react 中,我们通常将 App 包装在 index.js 中,而 RN 则不是这样。

      【讨论】:

        猜你喜欢
        • 2016-04-30
        • 2016-07-12
        • 2019-11-27
        • 2019-01-19
        • 2023-03-24
        • 2017-11-11
        • 2021-10-19
        • 1970-01-01
        • 2017-12-02
        相关资源
        最近更新 更多