如何在带有Redux ASP.NET Core的React中更改边栏的状态?

时间:2019-05-22 09:23:31

标签: reactjs asp.net-core redux

我是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的{​​{1}},最初设置为show。在上面的代码中,false存储在本地,但是我不确定使用Redux是否正确。

这是我想在其中使用按钮的state,它可能不是一直都在这里,但出于这个问题,我们假设它在这里。

src / components / Layout.js

layout

我认识到此按钮在上面的代码中不起作用,因为它无法访问toggleDrawer中的状态。

src / store / configureStore.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
}

src / store / Stage.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)
  );
}

以上是我相当粗鲁的尝试,以编写一个动作和一个reducer,使其能够将true或false传递到侧边栏并打开它。我需要帮助,当我单击布局中的菜单按钮时,如何(简单地)告诉redux更改边栏的状态?

感谢您的帮助和指导。

1 个答案:

答案 0 :(得分:0)

首先,我建议您更换

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足够长时,它将更具可读性。

现在,关于您的担忧,当前实现中缺少的步骤是状态/属性与化简器的映射。

看看下面的代码:

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-mapstatehttps://react-redux.js.org/using-react-redux/connect-mapdispatch,以更好地了解redux和react之间的联系。

NB:此代码示例通常出现在组件文件的末尾。

我们在这里拥有的是指定状态与我的组件的绑定connect(mapStateToProps,..)(myComponent)。 例如,指定状态是您在 src / store / Stage.js 中定义的值。

因此,根据您的情况,您必须在商店中connect使用组件,其操作完全如上所述。 然后,您必须映射要在组件状态中具有的化简器状态的信息。 看起来像这样:

const mapStateToProps = state => ({
    show: state.show,
});

基本上,这意味着“将组件状态的属性show与化简器的属性show绑定”。

如果reducer的show属性发生更改,则将通知该组件,并更新其show属性。