Yushan
Yushan

Reputation: 1047

Why is redux-thunk not working in Storybook?

I have integrated the Storybook UI development tool into my create-react-app.

Everything works fine until I add addon-redux as an add-on to the Storybook.

.storybook/main.js

module.exports = {
  stories: ["../src/components/**/*.stories.js"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/preset-create-react-app",
    "addon-redux", // This one
  ],
};

After I include that line, start to appear this message in my container component.

enter image description here

This is my container component.

TickerList.jsx

/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect } from "react";
import { connect } from "react-redux";
import { handleGetTickers } from "../../../actions/tickers";
import Ticker from "../../atoms/Ticker";

function TickerList({ tickers, getTickers }) {
  useEffect(() => {
    getTickers();
  }, []);

  return (
    <div className="ticker-list">
      {tickers.map((item, i) => (
        <Ticker
          key={i}
          name={item.name}
          value={item.value}
          percentage={item.percentage}
        />
      ))}
    </div>
  );
}

function mapStateToProps(state) {
  return {
    tickers: state.tickers,
  };
}

function mapDispatchToProps(dispatch) {
  return {
    getTickers: () => dispatch(handleGetTickers()),
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(TickerList);

This is my handleTickers action creator.

export const GET_TICKERS = "GET_TICKERS";

function getTickers(tickers) {
  return {
    type: GET_TICKERS,
    payload: tickers,
  };
}

// handleGetTickers
export function handleGetTickers() {
  return async (dispatch) => {

      const res = await fetchData("/data/tickers.json");
      if (res.ok) {
        const result = await res.json();
        dispatch(getTickers(result.data));
  }
}

As we all know, we need to include the thunk to handle these kinds of actions. So I include that when creating my Redux Store. This same store imports to the Storybook also.

store.js

import { createStore, compose, applyMiddleware } from "redux";
import { enhancer as withReduxEnhancer } from "addon-redux"; // This is use for connect the App Redux Store with Storybook
import invariant from "redux-immutable-state-invariant";
import { createLogger } from "redux-logger";
import thunk from "redux-thunk";
import reducer from "./reducers";

const createMiddlewareEnhancer = () => {
  const middleware = [thunk];
  if (process.env.NODE_ENV !== "production") {
    middleware.push(invariant());
    middleware.push(createLogger());
  }
  return applyMiddleware(...middleware);
};

const createEnhancer = () => {
  const enhancers = [];
  enhancers.push(createMiddlewareEnhancer());
  if (process.env.NODE_ENV !== "production") {
    enhancers.push(withReduxEnhancer);
  }
  return compose(...enhancers);
};

const store = createStore(reducer, createEnhancer());

export default store;

Then why is it working perfectly in the browser & not only in the Storybook? Did I miss something here?

Appreciate any help.

Upvotes: 0

Views: 708

Answers (2)

jf7
jf7

Reputation: 81

In at least some cases, the solution is in the thread referenced in the accepted answer (example uses Redux Toolkit):

I will have to think about this one a little as it could get tricky. My gut tells me this should be fixable by changing the order of store enhancers so that addon-redux is processed after the middlewares enchancer. That way the actions would be cleaned up before getting to the addon-redux enhancer.

You're right -- changing the order of the enhancers fixed it. For redux-toolkit, I did it the following way:

export const store = configureStore({
  reducer,
  middleware: getMiddleware(),
  enhancers: middlewares => [withReduxEnhancer, ...middlewares]
});

Upvotes: 0

Aleksandr Smyshliaev
Aleksandr Smyshliaev

Reputation: 420

Redux-thunk is a middleware, but addon-redux has issues with middlewares for now. But there also possible solution.

If you're using redux-thunk, your React UI made be triggering actions where the action is a function instead of an object. Since addon-redux ignores middlewares, the redux-thunk middleware gets ignore and then an error is thrown that Redux found an action that is a function.

Upvotes: 1

Related Questions