reactjs - 如何在 React with Redux ASP.NET Core 应用程序中更改侧边栏的状态?
问题描述
我是 React 和 Redux 的新手,我正在构建我的第一个 Web 应用程序。我正在构建的应用程序有一个我使用Material UI Drawer创建的侧边栏。它是由包含在侧边栏组件中的按钮触发的,但我不希望这样,我想做的是让按钮位于不同的组件中,并且状态drawer
由Redux
.
因为我是新手,所以我希望有人可以帮助我。这是我的代码。
我没有将我的商店连接到我的组件,因为我不清楚根据我的要求执行此操作的最佳方法
src/components/Sidebar.js
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from "react-router-dom";
import { withStyles } from '@material-ui/core/styles';
import Drawer from '@material-ui/core/Drawer';
import Button from '@material-ui/core/Button';
import List from '@material-ui/core/List';
import Divider from '@material-ui/core/Divider';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import MailIcon from '@material-ui/icons/Mail';
const styles = {
list: {
width: 250,
},
fullList: {
width: 'auto'
},
};
class Sidebar extends React.Component {
state = {
show: false,
};
toggleDrawer = (side, open) => () => {
this.setState({
[side]: open,
});
};
render() {
const { classes } = this.props;
const sideList = (
<div className={classes.list}>
<List>
<ListItem button component={Link} to="/">
<ListItemIcon>
<InboxIcon />
</ListItemIcon>
<ListItemText primary="Home" />
</ListItem>
</List>
<Divider />
<List>
{['All mail', 'Trash', 'Spam'].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</div>
);
return (
<div>
<Drawer open={this.state.show} onClose={this.toggleDrawer('show', false)}>
<div
tabIndex={0}
role="button"
onClick={this.toggleDrawer('show', false)}
onKeyDown={this.toggleDrawer('show', false)}
>
{sideList}
</div>
</Drawer>
</div>
);
}
}
Sidebar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Sidebar);
如您所见,最初设置为drawer
被state
调用。在上面的代码中,存储在本地,但我不确定使用 Redux 是否正确。show
false
state
这是我layout
希望按钮居住的地方,它可能不会一直在这里,但为了这个问题,让我们说它住在这里。
src/components/Layout.js
import React from 'react';
import { Container } from 'reactstrap';
import PropTypes from 'prop-types';
import Sidebar from './Sidebar';
export default props => (
<div className="beta">
<Sidebar />
<Button onClick={this.toggleDrawer('show', true)}>Open</Button>
<div className="container-fluid">
{props.children}
</div>
</div>
);
Container.propTypes = {
fluid: PropTypes.bool
}
我意识到这个按钮在上面的代码中不起作用,因为它无法访问 toggleDrawer 中的状态。
src/store/configureStore.js
import { applyMiddleware, combineReducers, compose, createStore } from 'redux';
import thunk from 'redux-thunk';
import { routerReducer, routerMiddleware } from 'react-router-redux';
import * as Stage from './Stage';
export default function configureStore(history, initialState) {
const reducers = {
sidebar: Stage.reducer
};
const middleware = [
thunk,
routerMiddleware(history)
];
// In development, use the browser's Redux dev tools extension if installed
const enhancers = [];
const isDevelopment = process.env.NODE_ENV === 'development';
if (isDevelopment && typeof window !== 'undefined' && window.devToolsExtension) {
enhancers.push(window.devToolsExtension());
}
const rootReducer = combineReducers({
...reducers,
routing: routerReducer
});
return createStore(
rootReducer,
initialState,
compose(applyMiddleware(...middleware), ...enhancers)
);
}
src/store/Stage.js
const sidebarOpen = 'SIDEBAR_OPEN';
const initialState = { show: false }
export const actionCreators = {
open: () => ({
type: sidebarOpen
})
};
export const reducer = (state, action) => {
state = state || initialState;
console.log("Initial State");
console.log(state)
if (action.type === sidebarOpen) {
return {
...state,
show: state.show = true
};
} else {
return {
...state,
show: state.show = false
}
}
return state;
};
以上是我相当粗略的尝试编写一个动作和一个减速器,它能够将真假传递给侧边栏并打开它。我需要帮助,我如何(简单地)告诉 redux 在单击布局中的菜单按钮时更改侧边栏的状态?
任何帮助和指导表示赞赏。
解决方案
首先,我建议你更换你的
if (action.type === sidebarOpen) {
someaction..
} else {
someaction..
}
和
switch(action.type)
{
case XXX: someaction; break;
case YYY: someaction; break;
default: somedefaultaction; break;
}
在src/store/Stage.js中,当 reducer 足够长时,它的可读性会更高。
现在,关于您的担忧,您当前的实现中缺少的步骤是 state/props 与 reducer 的映射。
看看下面的代码:
const mapStateToProps = state => ({
myVar: state.myVarFromReducer,
});
const mapDispatchToProps = dispatch => ({
expandFn: () => expand(dispatch),
});
export default connect(mapStateToProps, mapDispatchToProps)(myComponent);
让我们忽略mapDispatchToProps
,它不会用于我们的关注。
我邀请您查看https://react-redux.js.org/using-react-redux/connect-mapstate和https://react-redux.js.org/using-react-redux/connect-mapdispatch更好地理解 redux 和 react 之间的联系。
注意:此代码示例通常出现在组件文件的末尾。
我们这里有一个connect(mapStateToProps,..)(myComponent)
指定状态与我的组件的绑定。例如,指定的状态是您在src/store/Stage.js中定义的值。
因此,在您的情况下,您必须将connect
您的组件与商店联系起来,确切地说它是如何在上面完成的。然后你必须在你的组件状态中映射你想要拥有的减速器状态的信息。它看起来像这样:
const mapStateToProps = state => ({
show: state.show,
});
基本上,这意味着“将show
我的组件状态的属性与减速器的属性绑定show
”。
如果show
reducer的属性发生变化,会通知组件并show
更新他的属性。
推荐阅读
- r - 如何在函数中保持条件对象可用?
- javascript - 我不明白这段代码发生了什么
- javascript - React js RangeError:超出最大调用堆栈大小
- javascript - 添加到数组中的字段未显示必填字段验证错误
- encryption - 要加密的 AES 纯文本必须是 128 位
- html - 如何使html表单输出显示十进制数字?
- r - 计算向量中序列之间的差异,用于 R 中的距离矩阵
- git - 如何让 git 在不同的服务器上保持最新状态,并对它们进行单独的一次性更新?
- android - 未设置 Google Analytics(分析)页面价值
- hl7-fhir - 如何收集患者拥有资源 CarePlan 且状态为 active 的所有资源遭遇记录?