reactjsredux-toolkitumd

React: how to load redux-toolkit fully in browser (no npm)


I’m trying to load react-toolkit + JSX fully in my browser (I don’t want any npm-based setup to keep complexity low, and, importantly, to deploy the whole website via a single html file). However, I keep getting errors about some functions being undefined, so I guess my import is failing somehow. Do you know what I’m doing wrong?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Your App</title>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/@reduxjs/toolkit@1.9.3/dist/redux-toolkit.umd.js"></script>
  </head>
  <body>
    <div id="root"></div>

    <script type="text/babel">
      const { useState } = React;
      const { configureStore, createSlice, useDispatch, useSelector, Provider } = RTK;

      const counterSlice = createSlice({
        name: 'counter',
        initialState: 0,
        reducers: {
          increment: (state) => state + 1,
          decrement: (state) => state - 1
        }
      });

      const store = configureStore({
        reducer: counterSlice.reducer
      });

      // React component using JSX
      function Counter() {
        const counter = useSelector((state) => state);
        const dispatch = useDispatch();

        return (
          <div>
            <h1>Counter: {counter}</h1>
            <button onClick={() => dispatch(counterSlice.actions.increment())}>
              Increment
            </button>
            <button onClick={() => dispatch(counterSlice.actions.decrement())}>
              Decrement
            </button>
          </div>
        );
      }

      const container = document.getElementById('root');
      const root = ReactDOM.createRoot(container);
      root.render(
        <Provider store={store}>
          <Counter />
        </Provider>
      )
    </script>
  </body>
</html>


Solution

  • The Provider component and the useDispatch and useSelector hooks are react-redux exports. redux-toolkit doesn't provide these.

    Add <script src="https://unpkg.com/react-redux@8.0.5/dist/react-redux.min.js"></script> to the app scripts and access Provider, useDispatch, and useSelector from ReactRedux.

    <!DOCTYPE html>
    <html>
      <head>
        <title>My App</title>
        <meta charset="UTF-8" />
    
        <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
        <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
        <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
    
        <!-- Add this dependency -->
        <script src="https://unpkg.com/react-redux@8.0.5/dist/react-redux.min.js"></script>
    
        <script src="https://unpkg.com/@reduxjs/toolkit@1.9.3/dist/redux-toolkit.umd.js"></script>
      </head>
    
      <body>
        <div id="root"></div>
    
        <script type="text/babel">
          const { useState } = React;
    
          // Destructure from ReactRedux
          const { useDispatch, useSelector, Provider } = ReactRedux;
          const { configureStore, createSlice } = RTK;
    
          const counterSlice = createSlice({
            name: "counter",
            initialState: 0,
            reducers: {
              increment: (state) => state + 1,
              decrement: (state) => state - 1
            }
          });
    
          const store = configureStore({
            reducer: counterSlice.reducer
          });
    
          // React component using JSX
          function Counter() {
            const counter = useSelector((state) => state);
            const dispatch = useDispatch();
    
            return (
              <div>
                <h1>Counter: {counter}</h1>
                <button onClick={() => dispatch(counterSlice.actions.increment())}>
                  Increment
                </button>
                <button onClick={() => dispatch(counterSlice.actions.decrement())}>
                  Decrement
                </button>
              </div>
            );
          }
    
          const container = document.getElementById("root");
          const root = ReactDOM.createRoot(container);
          root.render(
            <Provider store={store}>
              <Counter />
            </Provider>
          );
        </script>
      </body>
    </html>
    

    Edit react-how-to-load-redux-toolkit-fully-in-browser-no-npm