Как я могу изменить состояние моей боковой панели в приложении React с Redux ASP.NET Core? - PullRequest
1 голос
/ 22 мая 2019

Я новичок в React и Redux и работаю над созданием своего первого веб-приложения.У приложения, которое я создаю, есть боковая панель, которую я создал с помощью 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, называемый show, который изначально установлен на false.В приведенном выше коде state хранится локально, но я не уверен, что это правильно для использования Redux.

Вот мой 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;
};

Вышесказанное - моя довольно грубая попытка написать действие и редуктор, которые могли бы передать значение true или false на боковую панель и открыть ее.Мне нужна помощь, как я могу (просто) сказать, чтобы redux изменил состояние моей боковой панели при нажатии кнопки меню, которая находится в моем макете?

Любая помощь и руководство приветствуются.

1 Ответ

0 голосов
/ 22 мая 2019

Прежде всего, я бы посоветовал вам заменить

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 это будетболее читабельным, когда редуктор будет расти достаточно.

Теперь, что касается вас, шаг, который отсутствует в вашей текущей реализации - это отображение состояний / реквизитов с помощью редуктора.

Посмотрите на следующий код:

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-response-redux / connect-mapstate и https://react -redux.js.org / using-Reaction-redux / connect-mapdispatch для лучшего понимания связи между redux и реакции.

Примечание: этот пример кода часто появляется в конце файла компонента.

Здесь мы имеем связь connect(mapStateToProps,..)(myComponent) указанного состояния с моим компонентом.Указанное состояние - это значения, которые вы определили, например, в src / store / Stage.js .

Итак, в вашей ситуации вам нужно connect ваш компонент с хранилищем,как именно это сделано выше.Затем вы должны отобразить информацию о состоянии редуктора, которое вы хотите иметь в состоянии вашего компонента.Это будет выглядеть так:

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

По сути, это означает «связать атрибут show состояния моего компонента с атрибутом редуктора show».

Если showПри изменении атрибута редуктора компонент будет уведомлен, а его атрибут show будет обновлен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...