useDispatch() 错误:找不到 react-redux 上下文值;请确保组件包装在 <Provider>

Posted

技术标签:

【中文标题】useDispatch() 错误:找不到 react-redux 上下文值;请确保组件包装在 <Provider>【英文标题】:useDispatch() Error: Could not find react-redux context value; please ensure the component is wrapped in a <Provider> 【发布时间】:2020-06-05 08:07:35 【问题描述】:

我正在尝试使用 React-Redux 库,但我收到标题错误。我用 Provider 包装了我的组件,但我仍然得到错误,只有当我实现 useDispatch() 钩子时。

应用程序运行良好,直到我添加了 useDispatch() 行。可以删除有关调度功能的其余行,但我仍然得到相同的错误。

如果您能帮助我,我将不胜感激。谢谢

这是我的代码:

import 'react-native-gesture-handler';
import NavigationContainer from '@react-navigation/native';
import Navigator from './navigation/Navigator';

import React, useEffect, useState, useCallback from 'react';
import SafeAreaView, StyleSheet, Text, View from 'react-native';

import createStore, combineReducers from 'redux';
import Provider, useDispatch from 'react-redux';
import dataReducer from './store/reducers/dataReducer';
import CONSTANTS from './constants/constants';
import saveInitialData from './store/actions/dataActions';

const App = () => 
  const [fetched, setFetched] = useState(initialState);

  const dispatch = useDispatch();

  const saveInitialDataHandler = useCallback(data => 
    dispatch(saveInitialData(data));
    callback;
  , []);

  const rootReducer = combineReducers(
    content: dataReducer,
  );

  const store = createStore(rootReducer);

  useEffect(() => 
    fetchData();
  , []);

  const fetchData = () => 
    fetch(CONSTANTS.database)
      .then(response => response.json())
      .then(responseJSON => 
        setFetched(true);
        saveInitialDataHandler(responseJSON);
      );
  ;

  if (!fetched) 
    return (
      <Provider store=store>
        <View stlye=flex: 1, alignItems: 'center', justifyContent: 'center'>
          <Text></Text>
        </View>
      </Provider>
    );
   else 
    return (
      <Provider store=store>
        <NavigationContainer>
          <SafeAreaView style=styles.SafeAreaView>
            <Navigator></Navigator>
          </SafeAreaView>
        </NavigationContainer>
      </Provider>
    );
  
;

const styles = StyleSheet.create(
  SafeAreaView: flex: 1,
);

export default App;

【问题讨论】:

【参考方案1】:

App 必须包含在 provider 中,因为您在其中使用了 useDispatch。现在还只是个孩子。 Provider 设置上下文,因此只有其子级才能访问它,而不是父级。

一种解决方案是为其创建一个包装器组件:

const AppWrapper = () => 
  const store = createStore(rootReducer);

  return (
    <Provider store=store> // Set context
      <App /> // Now App has access to context
    </Provider>
  )


const App = () => 
  const dispatch = useDispatch(); // Works!
...

【讨论】:

谢谢,它成功了。对于任何使用它的人,还记得导出您的 AppWrapper,而不是您的 App! 基本上确保使用 Provider 而不是 index.js 文件来包装您的 App 组件,该文件将 App 组件安装到 DOM。 您好,我遇到了同样的问题,当我尝试这种方法时,我收到“ReferenceError:找不到变量:rootReducer” rootReducer 是 OP 给他们的组合减速器的名称,您的名称可能会有所不同,具体取决于您如何设置减速器并导入它们。【参考方案2】:

也许您将 Provider 导入到 App.js 文件中。 Provider需要导入到文件index.js中。

/*index.js*/
import React from 'react';
import ReactDOM from 'react-dom';
import  Provider  from 'react-redux';
import  store  from './store/reduxStore';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

    ReactDOM.render(
  <React.StrictMode>
    <Provider store=store>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

【讨论】:

【参考方案3】:

如果您在运行npm run test 时遇到此错误,则问题与您的测试文件有关。

通过以下代码更新或替换您的app.test.tsx

注意:如果您还没有安装redux-mock-store,请不要忘记安装。

import React from 'react';
import  render  from '@testing-library/react';

import App from './App';

import  Provider  from 'react-redux';
import configureStore from 'redux-mock-store';

describe('With React Testing Library', () => 
    const initialState =  output: 10 ;
    const mockStore = configureStore();
    let store;

    it('Shows "Hello world!"', () => 
        store = mockStore(initialState);
        const  getByText  = render(
            <Provider store=store>
                <App />
            </Provider>
        );

        expect(getByText('Hello World!')).not.toBeNull();
    );
);

我在搜索 1 小时后得到了这个解决方案。 非常感谢OSTE

原解决方案:Github issues/8145 and solution link


使用此解决方案,如果您遇到 TypeError: window.matchMedia is not a function 之类的错误,请通过此方式解决。将这些行添加到您的 setupTests.ts 文件中。原解决方案链接***.com/a/64872224/5404861

global.matchMedia = global.matchMedia || function () 
  return 
    addListener: jest.fn(),
    removeListener: jest.fn(),
  ;
;

【讨论】:

【参考方案4】:

我对 react-native 应用程序的同一个 index.js 文件执行了此操作。 这样,您就不必导出和添加另一个文件,只是为了用提供​​者包装应用程序。

const ReduxProvider = () => 
    return(
        <Provider store=store>
            <App />
        </Provider>
    )


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

【讨论】:

【参考方案5】:

发生在我身上,当我将 React 组件作为函数调用时,没有将其用作虚拟 dom,Comp 被独立调用,而不是呈现为某个元素的子元素

function Comp() 
  const a = useSelector(selectA); // throws error

Comp();

所以在我的情况下,解决方案是调用 Comp 和一个组件,而不是作为一个函数 即&lt;Comp /&gt;

【讨论】:

所以。解决方案是什么? 解决方案是使用一级间接 - 即在 Comp 中调用选择器。这也是公认的解决方案。

以上是关于useDispatch() 错误:找不到 react-redux 上下文值;请确保组件包装在 <Provider>的主要内容,如果未能解决你的问题,请参考以下文章

找不到模块“react-scroll-to-bottom”的声明文件

React-redux useDispatch() Uncaught TypeError

为啥 useDispatch 重新渲染父组件?

找不到错误:找不到页面(404)

无法启动 Terminal Services 服务。错误 126: 找不到指定的模块。

如何清理 useEffect 中的 Redux“useDispatch”操作?