Next.js Discord

Discord Forum

Global state management in Nextjs

Unanswered
Scottish Deerhound posted this in #help-forum
Open in Discord
Scottish DeerhoundOP
I am trying to connect my frontend with websocket on the backend, I need to make the connected websocket variable accessible to other components. I tried to add it to the functions for making the connection inside _app.js which is a top level component, but the issue am facing right now is, I tried to dispatch my redux action so I can call the function that runs the connection, but I got an error that says:
Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>


Here is what my code looks like socket-connection.js:

2 Replies

Scottish DeerhoundOP
import { createSlice } from "@reduxjs/toolkit";

const socketConnectionSlice = createSlice({
  name: "socketConnection",
  initialState: {
    newWs: null,
  },
  reducers: {
    // Connect websocket and keep the connection alive
    socketConnection: (state, action) => {
      const HEARTBEAT_TIMEOUT = 1000 * 5 + 1000 * 1; // 5 + 1 second
      const HEARTBEAT_VALUE = 1;

      const ws = new WebSocket(process.env.WEB_SOCKET_BACKEND_URL);

      function heartbeat() {
        if (!ws) return;
        else if (!!ws.pingTimeout) clearTimeout(ws.pingTimeout);

        ws.pingTimeout = setTimeout(() => {
          ws.close();
          // business logic for deciding whether or not to reconnect
        }, HEARTBEAT_TIMEOUT);

        const data = new Uint8Array(1);
        data[0] = HEARTBEAT_VALUE;
        ws.send(data);
      }

      ws.onopen = () => {
        console.log("WebSocket connection opened");
        heartbeat();
      };

      ws.onmessage = () => {
        heartbeat();
      };

      ws.onclose = () => {
        if (ws.pingTimeout) clearTimeout(ws.pingTimeout);
      };

      state.newWs = ws;
    },
    // Close websocket
    closeWebSocket: (state, action) => {
      if (state.ws && state.ws.readyState === WebSocket.OPEN) {
        ws.close();
      }
    },
  },
});

export const socketConnectionActions = socketConnectionSlice.actions;
export default socketConnectionSlice;
This is _app.js
export default function App({ Component, pageProps, router }) {
  const dispatch = useDispatch();
  const getLayout = Component.getLayout || ((page) => <Layout children={page} />);

  useEffect(() => {
    dispatch(socketConnectionActions.socketConnection());

    return () => {
      dispatch(socketConnectionActions.closeWebSocket());
    };
  });

  return (
    <Provider store={store}>
      {getLayout(
        <motion.div
          key={router.route}
          initial="pageInitial"
          animate="pageAnimate"
          exit="pageExit"
          variants={{
            pageInitial: {
              opacity: 0,
            },
            pageAnimate: {
              opacity: 1,
            },
            pageExit: {
              opacity: 0,
            },
          }}
        >
          <main className={`${openSans.variable}`}>
            <Component {...pageProps} />
          </main>
        </motion.div>
      )}
    </Provider>
  );
}


Pls I need help accessing the variable globally.