【问题标题】:Error: Could not find "store" in the context of "Connect(AppProvider)"错误:在“Connect(AppProvider)”的上下文中找不到“store”
【发布时间】:2021-05-28 22:06:45
【问题描述】:

我正在开发一个带有 expo 的 react-native 应用程序。

我的组件之间需要一些共享存储,所以我转向了 redux。

但是,经过几个小时的努力,我无法让它工作:我不断收到臭名昭著的错误“错误:在“连接(AppProvider)”的上下文中找不到“商店”。

但是,我觉得一切都很好。我不明白错误来自哪里。有谁知道我做错了什么?

这是我的 index.js 文件:

import React from 'react'
import { Provider } from 'react-redux' 
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'
import App from './App.js'
import store from './store/store.js'
import { setNCServer, setToken } from './store/actions';
import { registerRootComponent } from 'expo';
 
const AppProvider = () => {
    return (
      <Provider store={store}>
        <App />
      </Provider>
    )
}
 
// Initialise store
const mapDispatchToProps = dispatch => (
    bindActionCreators({
      setNCServer,
      setToken,
    }, dispatch)
);
const mapStateToProps = (state) => {
    return state
};
const connector = connect(mapStateToProps, mapDispatchToProps)
const AppRoot = connector(AppProvider);
export default registerRootComponent(AppRoot);

这是我的 store.js 文件:

import { createStore } from 'redux';
import CombinedReducers from './reducers.js';
 
const store = createStore(CombinedReducers);
 
export default store

这是我的 reducers.js 文件:

import { combineReducers } from 'redux';

const tokenReducer = (state = null, action) => {
  switch (action.type) {
    case 'set':
        return action.payload;  
    default:
      return state
  }
};

const NCServerReducer = (state = null, action) => {
  switch (action.type) {
    case 'set':
        return action.payload;  
    default:
      return state
  }
};

export default combinedReducers({
  NCServer: NCServerReducer,
  token: tokenReducer
});

这是我的 action.js 文件:

export const setNCServer = NCServer => (
  {
    type: 'set',
    payload: NCServer,
  }
);

export const setToken = token => (
  {
    type: 'set',
    payload: token,
  }
);

======== 更新 =========

根据 Pera 的回答 (https://stackoverflow.com/a/67746329/16063826),我尝试将我的 connect 逻辑移动到 App 组件中。

不太确定该怎么做,我的index.js 文件现在看起来像这样:

import React from 'react';
import { Provider } from 'react-redux' ;
import App from './App.js';
import store from './store/store.js';
 
export default class AppProvider extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <App />
      </Provider>
    )
  }
}

还有我的App.js 文件,像这样:

import React from 'react';

// Persistent storage
import AsyncStorage from '@react-native-async-storage/async-storage';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'
import { setNCServer, setToken } from './store/actions';
import { registerRootComponent } from 'expo';

// Navigation
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import Login from './Login';
import Home from './Home';
import BoardScreen from './BoardScreen';
import BoardDetailsScreen from './BoardDetailsScreen';
import CardDetailsScreen from './CardDetailsScreen';

// For creating an URL handler to retrieve the device token
import * as Linking from 'expo-linking';

// Create Stack navigator
const Stack = createStackNavigator()

// Application
class App extends React.Component {

  constructor(props) {
    super(props)
    
    // Retrieve token from storage if available
    AsyncStorage.getItem('token').then(token => {
      this.props.state.setToken(token)  
    })

    // Register handler to catch Nextcloud's redirect after successfull login
    Linking.addEventListener('url', (url) => {this.handleRedirect(url)})
  }

  // Function to retrieve the device's token and save it after user logged in
  handleRedirect = async (url) => {
    if (url.url.startsWith('nc://login/server')) {
      try {
        token = url.url.substring(url.url.lastIndexOf(':'))
        console.log('Persisting token', token)
        AsyncStorage.setItem('token', token);  
        this.props.state.setToken(token)
      } catch (e) {
        // TODO
      } 
    }
  }

  render() {
    if (this.state.token === null) {
      // No token is stored yet, we need to get one
      return (
          <NavigationContainer>
            <Stack.Navigator>
              <Stack.Screen name="Home" component={Home} />
              <Stack.Screen name="Login" component={Login} />
            </Stack.Navigator>
          </NavigationContainer>
      ) 
    } else {
      return (
          <NavigationContainer>
            <Stack.Navigator>
              <Stack.Screen name="AllBoard" component={BoardScreen} options={{title: 'All boards'}} />
              <Stack.Screen name="BoardDetails" component={BoardDetailsScreen} options={{title: 'Board details'}} />
              <Stack.Screen name="CardDetails" component={CardDetailsScreen} options={{title: 'Card details'}} />
            </Stack.Navigator>
          </NavigationContainer>
      )
    }
  }
}

// Initialise store
const mapDispatchToProps = dispatch => (
  bindActionCreators({
    setNCServer,
    setToken,
  }, dispatch)
);
const mapStateToProps = (state) => {
  return state
};
const connector = connect(mapStateToProps, mapDispatchToProps)
const AppRoot = connector(App);
export default registerRootComponent(AppRoot);

但我仍然遇到同样的错误。

错误日志对我来说有点奇怪:

Info Before connect
13:04
Info After connect
13:04
Info before createStore CombinedReducers: [Function combination]
13:04
Info after createStore 
13:04
Info Running application on Mon iPhone.
13:04
Error Error: Could not find "store" in the context of "Connect(App)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(App) in connect options.
13:04

This error is located at:
    in Connect(App) (created by ExpoRoot)
    in ExpoRoot (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in DevAppContainer (at AppContainer.js:121)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)

所以,当我启动应用程序时,它会遍历 connectcreateStore 函数,然后在 ExpoRoot 中失败...。这里可能出了什么问题?

【问题讨论】:

    标签: react-native redux expo


    【解决方案1】:

    错误是您在使用商店实际初始化 Redux 上下文之前尝试使用 connect。 尝试将connectApp 组件一起使用,这样AppProvider 已经渲染并设置了商店。

    【讨论】:

    • 好吧,您的问题陈述是有道理的:我可以在我的应用程序中想象这样的问题。但是,我无法理解您的解决方案。我尝试将connect 函数移至App,但并没有解决问题。我将编辑我的问题以尝试提供更多信息
    【解决方案2】:

    我想通了:主要问题是export default registerRootComponent(); 必须在index.js

    【讨论】:

      猜你喜欢
      • 2021-10-19
      • 1970-01-01
      • 2019-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-08
      • 2017-11-11
      • 1970-01-01
      相关资源
      最近更新 更多