2

I'm trying to use redux with NextJS and class components but can't figure out how to get rid of this error:

Error: Could not find "store" in the context of "Connect(CounterDisplay)". Either wrap the root component in a <Provider>, or pass a custom React context provider to and the corresponding React context consumer to Connect(CounterDisplay) in connect options.

// pages/_app.js

import '../styles/globals.css';
import 'bootstrap/dist/css/bootstrap.css';
import {Provider} from 'react-redux';
import {useStore} from '../core/redux/store';

export default function App({Component, pageProps}) {
  const store = useStore(pageProps.initialReduxState);

  return (
      <Provider store={store}>
        <Component {...pageProps} />
      </Provider>
  );
}
// pages/index.js

import React from 'react';
import Page from '../components/page'
import CounterDisplay from '../components/CounterDisplay';

export default function Index() {
  // return <Page />
  return (
      <React.Fragment>
        <CounterDisplay/>
      </React.Fragment>
  )
}
// components/CounterDisplay.js

import React from 'react';
import connect from 'react-redux/lib/connect/connect';

class CounterDisplay extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    return (
        <div>
          <span>{this.props.count}</span>
        </div>
    );
  }
}


function mapStateToProps(state, ownProps) {
  return {
    count: state.count
  }
}

export default connect(mapStateToProps)(CounterDisplay);

Weird thing is that I already wrapped the root component in a <Provider> so it should work fine according to the error message.

EDIT:

// core/redux/store

import {useMemo} from 'react';
import {createStore, applyMiddleware} from 'redux';
import {composeWithDevTools} from 'redux-devtools-extension';

let store;

const initialState = {
  lastUpdate: 0,
  light: false,
  count: 0,
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'TICK':
      return {
        ...state,
        lastUpdate: action.lastUpdate,
        light: !!action.light,
      };
    case 'INCREMENT':
      return {
        ...state,
        count: state.count + 1,
      };
    case 'DECREMENT':
      return {
        ...state,
        count: state.count - 1,
      };
    case 'RESET':
      return {
        ...state,
        count: initialState.count,
      };
    default:
      return state;
  }
};

function initStore(preloadedState = initialState) {
  return createStore(
      reducer,
      preloadedState,
      composeWithDevTools(applyMiddleware()),
  );
}

export const initializeStore = (preloadedState) => {
  let _store = store ?? initStore(preloadedState);

  // After navigating to a page with an initial Redux state, merge that state
  // with the current state in the store, and create a new store
  if (preloadedState && store) {
    _store = initStore({
      ...store.getState(),
      ...preloadedState,
    });
    // Reset the current store
    store = undefined;
  }

  // For SSG and SSR always create a new store
  if (typeof window === 'undefined') return _store;
  // Create the store once in the client
  if (!store) store = _store;

  return _store;
};

export function useStore(initialState) {
  const store = useMemo(() => initializeStore(initialState), [initialState]);
  return store;
}
2
  • It might be related to useStore method. Could you share your redux/store.js code and also theComponent component's code that you call in App? Commented May 16, 2021 at 18:57
  • 1
    Thanks for your answer. The Component used in _app is the default component that Next JS uses to initialize pages (nextjs.org/docs/advanced-features/custom-app). I will update the question with the content of redux/store Commented May 16, 2021 at 19:15

1 Answer 1

1

In your CounterDisplay component you need to change import of connect :

import connect from 'react-redux/lib/connect/connect';

line to:

import {connect} from 'react-redux';

react-redux most probably can not see the same store if you do not import it from the addon's root folder.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.