Компонент React-Redux не показывает новые реквизиты в магазине - PullRequest
0 голосов
/ 16 декабря 2018

Я пытаюсь создать свой собственный компонент оповещения с помощью реакции (также в данном случае, Bootstrap v4).В основном, если что-то происходит, о чем пользователь должен быть уведомлен, создайте сообщение, поместите его в хранилище и отреагируйте, сделав предупреждение.Я знаю, что то, что я делаю, должно быть возможным, однако я достаточно новичок, чтобы реагировать на то, что я что-то упускаю / не понимаю в том, как реагирует, что не приводит к отображению предупреждений.

Во-первых,Я предупреждаю о доступности всех других компонентов, поэтому помещаю его в свой app.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import AppRouter from './routers/AppRouter';
import configureStore from './store/configureStore';

import Alerts from './components/controls/Alerts';

const { store, persistor } = configureStore();

const jsx = (
    <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
            <Alerts />
            <AppRouter />
        </PersistGate>
    </Provider>
);

ReactDOM.render(jsx, document.getElementById('root'));

Далее идут компоненты для Alerts.Сначала действия:

// DISPLAY_ALERT
export const displayAlert = (message, severity) => ({
    type: 'DISPLAY_ALERT',
    message: message,
    severity: severity
});

// DISMISS_ALERT
export const dismissAlert = (id) => ({
    type: 'DISMISS_ALERT',
    id: id
});

Редуктор:

const alertsDefaultState = [];

const alertNotify = (state, action) => {
    let queue = state;

    if (!queue || !Array.isArray(queue))
        queue = [];

    let newAlert = {
        id: getUniqueId(),
        message: action.message,
        severity: action.severity
    };

    queue.push(newAlert);

    return queue;
};

const alertDismiss = (state, action) => {
    const newQueue = state.filter((element) => element.id !== action.id);

    return newQueue;
};

const getUniqueId = () => {
    return (Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase();
};

export default (state = alertsDefaultState, action) => {
    switch (action.type) {
        case 'DISPLAY_ALERT':
            return alertNotify(state, action);
        case 'DISMISS_ALERT':
            return alertDismiss(state, action);
        case 'LOG_OUT_OF_API':
            return [];
        default:
            return state;
    }
};

Магазин:

import { createStore, combineReducers } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import alertsReducer from '../reducers/alerts';

export default () => {
    const persistConfig = {
        key: 'root',
        storage,
    };

    let reducers = combineReducers({
        // Other reducers
        alerts: alertsReducer
    });

    let store = createStore(
        persistReducer(persistConfig, reducers),
        window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );

    let persistor = persistStore(store);

    return { store, persistor };
};

И, наконец, Alerts компоненты:

import React from 'react';
import { connect } from 'react-redux';
import { dismissAlert } from '../../actions/alerts';

class Alerts extends React.Component {
    constructor(props) {
        super(props);
    }

    getAlerts = () => {
        if (!this.props.alerts || this.props.alerts.length === 0)
            return null;

        const alertFixed = {
            position:'fixed',
            top: '0px',
            left: '0px',
            width: '100%',
            zIndex: 9999,
            borderRadius: '0px'
        };

        return (
            <div style={alertFixed}>
                {
                    this.props.alerts.map((alert) => {
                        const alertClass = `alert alert-${alert.severity} alert-dismissible m-4`
                        setTimeout(() => {
                            this.props.dispatch(dismissAlert(alert.id));
                        }, 5000);
                        return (
                            <div key={alert.id} id={alert.id} className={alertClass} role="alert">
                                <button type="button" className="close" data-dismiss="alert" aria-label="Close">
                                    <span aria-hidden="true">&times;</span>
                                </button>
                                { alert.message }
                            </div>
                            );
                        }
                    )
                }
            </div>
        );
    }

    render() {
        return this.getAlerts()
    }
}

const mapStateToProps = (state) => {
    return {
        alerts: state.alerts
    }
};

export default connect(mapStateToProps)(Alerts);

И, наконец, у меня есть класс const для типов предупреждений:

export default {
    Info: 'info',
    Success: 'success',
    Warning: 'warning',
    Error: 'danger',
};

Если я запусту приведенный выше код и у него будет что-то в alerts store, он будет обработан.Однако, если я добавлю что-то в хранилище по событию, например по нажатию кнопки, я увижу, что предупреждение добавляется в хранилище, но компонент не добавит его в DOM.

Что такоеЯ пропал?

РЕДАКТИРОВАТЬ:

Вот код песочницы

1 Ответ

0 голосов
/ 16 декабря 2018

Массивы являются ссылочными типами в Javascript

В вашем

const alertNotify = (state, action) => {
    let queue = state;

    if (!queue || !Array.isArray(queue))
        queue = [];

    let newAlert = {
        id: getUniqueId(),
        message: action.message,
        severity: action.severity
    };

    queue.push(newAlert);

    return queue;
};

Вместо того, чтобы делать что-то подобное

 let queue = state;

Вам необходимо сделать копиюиз него (вместо ссылки на него), а затем выполните

queue.push(newAlert);

, т. е. измените исходное объявление очереди на это (я использую оператор распространения, чтобы сделать копию пройденного состояния, а затем нажимаю newAlert в вашемочередь

let queue = [...state];

Поскольку ваша очередь при возврате, не имела состояния в ней

Это условие было запущено

 if (!this.props.alerts || this.props.alerts.length === 0)
...