我使用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并不关心传递的函数是否同步。
非常感谢所有前期的帮助!
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并再次返回相同的页面