当前位置: 首页 > 知识库问答 >
问题:

(next.js)Thunk不会触发减速器

顾永福
2023-03-14

我使用next.js提供的with-redux示例(https://github.com/zeit/next.js/tree/canary/examples/with-redux)在next.js中设置了React-Redux。此外,我还设置了thunk,因为将来大多数redux调用都将是异步的(现在只是初始状态,将被更改)。

当我现在尝试使用thunk调度函数时,还原器从未被触发。

现在我已经到了了解如何使这个工作的尽头了。(注:这是我第一次尝试用next设置redux,直到现在我只通过路由结构清晰的客户端应用来完成)

MenustatusActions.js

import * as types from "./actionTypes";

export function changeMenu(id) {
  return { type: types.MENU_CHANGE, id };
}

export function changeMenuStatus(id) {
  return function(dispatch) {
    debugger;
    return dispatch(changeMenu(id));
  };
}

MenustatusReducer.js

import * as types from "../actions/actionTypes";
import initialState from "./initialState";

export default function menuStatusReducer(
  state = initialState.menuState,
  action
) {
  switch (action.type) {
    case types.MENU_CHANGE:
      return Object.assign([], state, {
        [action.id - 1]: !state[action.id - 1]
      });
    default:
      return state;
  }
}

ConfigureStore.js

import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunkMiddleware from "redux-thunk";
import reduxImmutableStateInvariant from "redux-immutable-state-invariant";
import rootReducer from "./reducers";
import inState from "./reducers/initialState";

export default function initializeStore(initialState = inState) {
  return createStore(
    rootReducer,
    initialState,
    composeWithDevTools(
      applyMiddleware(thunkMiddleware, reduxImmutableStateInvariant())
    )
  );
}

with-redux-store.js(从上面的next.js github复制[改编])

/* eslint-disable no-param-reassign */
/* eslint-disable react/jsx-props-no-spreading */
/* eslint-disable react/prop-types */
/* eslint-disable no-underscore-dangle */
/* eslint-disable-next-line no-param-reassign */

import React from "react";
import initializeStore from "./redux/configureStore";

const isServer = typeof window === "undefined";
const __NEXT_REDUX_STORE__ = "__NEXT_REDUX_STORE__";

function getOrCreateStore(initialState) {
  // Always make a new store if server, otherwise state is shared between requests
  if (isServer) {
    return initializeStore(initialState);
  }

  // Create store if unavailable on the client and set it on the window object
  if (!window[__NEXT_REDUX_STORE__]) {
    window[__NEXT_REDUX_STORE__] = initializeStore(initialState);
  }
  return window[__NEXT_REDUX_STORE__];
}

export default App => {
  return class AppWithRedux extends React.Component {
    static async getInitialProps(appContext) {
      // Get or Create the store with `undefined` as initialState
      // This allows you to set a custom default initialState
      const reduxStore = getOrCreateStore();

      // Provide the store to getInitialProps of pages

      appContext.ctx.reduxStore = reduxStore;

      let appProps = {};
      if (typeof App.getInitialProps === "function") {
        appProps = await App.getInitialProps(appContext);
      }

      return {
        ...appProps,
        initialReduxState: reduxStore.getState()
      };
    }

    constructor(props) {
      super(props);
      this.reduxStore = getOrCreateStore(props.initialReduxState);
    }

    render() {
      return <App {...this.props} reduxStore={this.reduxStore} />;
    }
  };
};

_app.js(复制自上面的next.js示例github)

import App from "next/app";
import React from "react";
import { Provider } from "react-redux";
import withReduxStore from "../src/with-redux-store";


class MyApp extends App {
  render() {
    const { Component, pageProps, reduxStore } = this.props;
    return (
      <Provider store={reduxStore}>
        <Component {...pageProps} />
      </Provider>
    );
  }
}

export default withReduxStore(MyApp);

调用存储的组件(所有页面中使用的Toplevel组件)

import React from "react";
import { connect } from "react-redux";
import { makeStyles } from "@material-ui/core/styles";
import Drawer from "@material-ui/core/Drawer";
import CssBaseline from "@material-ui/core/CssBaseline";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import List from "@material-ui/core/List";
import Typography from "@material-ui/core/Typography";
import Divider from "@material-ui/core/Divider";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import { Collapse } from "@material-ui/core";

import PropTypes from "prop-types";

import Link from "next/link";

import sideMenuItems from "./sideMenuItems";
import { changeMenuStatus } from "../redux/actions/menuStatusActions";

const drawerWidth = 240;

const useStyles = makeStyles(theme => ({
  root: {
    display: "flex"
  },
  appBar: {
    width: `calc(100% - ${drawerWidth}px)`,
    marginLeft: drawerWidth
  },
  drawer: {
    width: drawerWidth,
    flexShrink: 0
  },
  drawerPaper: {
    width: drawerWidth
  },
  toolbar: theme.mixins.toolbar,
  content: {
    flexGrow: 1,
    backgroundColor: theme.palette.background.default,
    padding: theme.spacing(3)
  }
}));

function Layout({ title, menuState, changeMenuStatusAction }) {
  const classes = useStyles();
  const open = menuState;

  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar position="fixed" className={classes.appBar}>
        <Toolbar>
          <Typography variant="h6" noWrap>
            {title}
          </Typography>
        </Toolbar>
      </AppBar>
      <Drawer
        variant="permanent"
        classes={{
          paper: classes.drawerPaper
        }}
        anchor="left"
      >
        <div className={classes.toolbar} />
        <Divider />
        <List>
          {sideMenuItems.map(item => (
            <>
              <ListItem
                key={`item${item.id}`}
                button
                onClick={() => changeMenuStatusAction(item.id)}
              >
                <ListItemText primary={item.title} />
              </ListItem>
              <Collapse
                key={`collapse${item.id}`}
                in={open[item.id - 1]}
                timeout="auto"
              >
                <List component="div" disablePadding key={`List${item.id}`}>
                  {item.children.map(childItem => (
                    <Link
                      key={`Link${childItem.id}`}
                      href={`${item.href}${childItem.href}`}
                    >
                      <ListItem button key={`ListItem${childItem.id}`}>
                        <ListItemText secondary={childItem.title} />
                      </ListItem>
                    </Link>
                  ))}
                </List>
              </Collapse>
            </>
          ))}
        </List>
      </Drawer>
      <main className={classes.content}>
        <div className={classes.toolbar} />
        Test 1234!
      </main>
    </div>
  );
}

Layout.propTypes = {
  title: PropTypes.string.isRequired,
  // eslint-disable-next-line react/forbid-prop-types
  menuState: PropTypes.any.isRequired,
  changeMenuStatusAction: PropTypes.func.isRequired
};

function mapStateToProps(state) {
  return {
    menuState: state.menuState
  };
}

const mapDispatchToProps = dispatch => ({
  changeMenuStatusAction: dispatch(changeMenuStatus)
});

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

结果是没有错误的,但本质上发生的是什么都没有。尝试在thunk中添加一个“调试器”,但它从未被触发。

它必须是异步的才能工作吗?据我所知,ThunkMiddware并不关心传递的函数是否同步。

非常感谢所有前期的帮助!

共有1个答案

鲁旭
2023-03-14

MapDispatchToprops应该是一个输入Dispatch函数,然后您必须用Dispatch包装您的操作。将MapDispatchToprops更改为以下内容

const mapDispatchToProps = (dispatch) => ({
  changeMenuStatusAction: (id) => dispatch(changeMenuStatus(id))
});

然后,您可以使用ChangeMenustatusAction作为道具,并使用它触发您的操作。希望有帮助:)。

 类似资料:
  • 正如标题所说,我根本无法让Quartz.net工作。我从NuGet获得了最新版本的Quartz.net(2.2.1)、Common.Logging(2.1.2)、Common.Logging.NLog(2.0.0)和NLog(2.1.0)。触发器没有被触发,而且石英绝对没有记录任何东西。我猜我搞砸了配置。 我的应用程序配置: 有一个作业和一个触发器与之相关: 调度程序将启动,作业和触发器将正确添加

  • 当编写< code>redux-thunk函数(称为thunks)时,有许多样板文件可以很容易地提取出来。例如,在我们的大多数异步API调用中,我们执行以下操作,没有任何副作用: 轻松点。虽然这至少涵盖了我们70%的请求,但我确信有一种优雅的方式可以将上述代码抽象为类似这样的代码(伪代码): 当我们需要检查状态和其他副作用时,我们可以返回到适当的thunk。尽管在大多数情况下...我们可以把它砍掉

  • 问题内容: 我试图设置一个监听器来确定何时按下输入按钮,但是根本没有触发。我在装有Android 4.2.2的LG Nexus 4上进行了测试。可以在具有Android 2.3的Amazon Kindle Fire上使用,并且无处可用!我也无法为按钮设置文本。这是代码: 我究竟做错了什么?我怎样才能解决这个问题? 问题答案: 您可以使用TextWatcher。

  • 问题内容: 我正在尝试在应用程序中使用AngularJS,并在某种程度上取得了成功。 我能够获取数据并将其显示给用户。我有一个按钮,我想通过该按钮发布DELETE请求。下面是我的代码。 这是获取信息并将其显示给用户的功能。 数据已获取并正确显示。 但是,单击删除按钮后,不会触发其中的代码。在GoogleChrome浏览器的开发人员工具中,我可以看到为代码生成了有效值,但未触发代码。从我尝试去掉花括

  • 我有这个脚本: HTML中的用法: 由于某些原因,它的工作,如果页面重新加载一半,但不,它没有开火,在它工作之前,所以我不知道发生了什么。我在wordpress网站上使用这个。

  • 我正在尝试验证表单字段集的输入值,并在发生无效输入时使Thymeleaf显示一些错误消息。但不知何故,以下Thymeleaf命令从未以正确的方式得到解决: 关于我的环境的更多信息,我想不会有什么坏处: 根据Spring GS指南“验证表单输入”,我实现了相关的控制器方法,如下所示: 控制器: 当我向控制器提交无效的表单输入时,它会根据需要运行if子句,这样打印log.infos并再次返回相同的页面