首页 > 解决方案 > 如何在 React with Redux ASP.NET Core 应用程序中更改侧边栏的状态?

问题描述

我是 React 和 Redux 的新手,我正在构建我的第一个 Web 应用程序。我正在构建的应用程序有一个我使用Material UI Drawer创建的侧边栏。它是由包含在侧边栏组件中的按钮触发的,但我不希望这样,我想做的是让按钮位于不同的组件中,并且状态drawerRedux.

因为我是新手,所以我希望有人可以帮助我。这是我的代码。

我没有将我的商店连接到我的组件,因为我不清楚根据我的要求执行此操作的最佳方法

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);

如您所见,最初设置为drawerstate调用。在上面的代码中,存储在本地,但我不确定使用 Redux 是否正确。showfalsestate

这是我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 在单击布局中的菜单按钮时更改侧边栏的状态?

任何帮助和指导表示赞赏。

标签: reactjsasp.net-coreredux

解决方案


首先,我建议你更换你的

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-mapstatehttps://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”。

如果showreducer的属性发生变化,会通知组件并show更新他的属性。


推荐阅读