Я работаю над этим проектом, где интерфейс находится в React с UIkit для пользовательского интерфейса. Интеграция между частями выглядит плохо реализованной. Я объясню почему. Есть компонент Modal, что-то вроде
export class Modal extends Component {
static getByName = name => UIkit.modal(`[data-modal-name='${name}']`)
static show = name => {
const modal = Modal.getByName(name)
if (modal) modal.show()
}
static hide = name => {
const modal = Modal.getByName(name)
if (modal) modal.hide()
}
render() {
// a modal
}
}
это используется таким образом
export const LoginFormModal = props => (
<Modal name = "login-form" className = "login-form-modal" hideClose>
<LoginForm />
</Modal>
)
и show / hide вызывается программно там, где это необходимо (даже действия redux)
Modal.hide("login-form")
это в действии Redux, например
export const login = credentials => {
return dispatch => {
dispatch(showLoader())
API.authentication.login(
credentials,
response => {
setCurrentUser(
Object.assign({}, response.user, { user_id: response.user.id })
)
Modal.hide("login-form")
dispatch(loginSucceded(response))
dispatch(hideLoader())
dispatch(push("/"))
dispatch(fetchNotificationsCounter())
},
error => {
dispatch(loginFailed(error))
dispatch(hideLoader())
}
)
}
}
Кажется, это работает. Пока вы не оставите компонент. Когда вы вернетесь к нему, второй раз программно скрытие больше не работает.
Кто-нибудь может подсказать мне, как интегрировать части более соответствующим образом?
В качестве примера добавлено действие redux
Работает с первого раза, мой модал закрыт программно. Но, если я оставлю компонент (отключен), я вернусь к нему, больше никогда не будет работать.
вы должны получить состояние, указывающее, что вы вошли в систему на LoginFormModal





Что мне не нравится, и это определенно не "способ реагирования", так это то, что код изменяет состояние непосредственно от создателя действия (!). От React docs:
For example, instead of exposing open() and close() methods on a Dialog component, pass an isOpen prop to it.
Так что, если бы у вас был один модальный файл, который контролировался бы состоянием редукции? Вот возможная реализация:
ModalWindow - будет реагировать на изменения состояния и рендерить в зависимости от того, что в магазине:
import React from 'react';
import InfoContent from './InfoContent';
import YesOrNoContent from './YesOrNoContent';
import { MODAL_ACTION } from './modal/reducer';
class ModalWindow extends React.Component {
renderModalTitle = () => {
switch (this.props.modalAction) {
case MODAL_ACTION.INFO:
return 'Info';
case MODAL_ACTION.YES_OR_NO:
return 'Are you sure?';
default:
return '';
}
};
renderModalContent = () => {
switch (this.props.modalAction) {
case MODAL_ACTION.INFO:
return <InfoContent />;
case MODAL_ACTION.YES_OR_NO:
return <YesOrNoContent />;
default:
return null;
}
};
render() {
return (
this.props.isModalVisible ?
<div>
<p>{this.renderTitle()}</p>
<div>
{this.renderModalContent()}
</div>
</div>
:
null
);
}
}
export default connect((state) => ({
modalAction: state.modal.modalAction,
isModalVisible: state.modal.isModalVisible,
}))(ModalWindow);
модальный редуктор он предоставит API для отображения / скрытия модального окна в приложении:
export const SHOW_MODAL = 'SHOW_MODAL';
export const HIDE_MODAL = 'HIDE_MODAL';
const INITIAL_STATE = {
isModalVisible: false,
modalAction: '',
};
export default function reducer(state = INITIAL_STATE, action) {
switch (action.type) {
case SHOW_MODAL:
return { ...state, isModalVisible: true, modalAction: action.modalAction };
case HIDE_MODAL:
return { ...state, isModalVisible: false };
default:
return state;
}
}
export const MODAL_ACTION = {
YES_OR_NO: 'YES_OR_NO',
INFO: 'INFO',
};
const showModal = (modalAction) => ({ type: SHOW_MODAL, modalAction });
export const hideModal = () => ({ type: HIDE_MODAL });
export const showInformation = () => showModal(MODAL_ACTION.INFO);
export const askForConfirmation = () => showModal(MODAL_ACTION.YES_OR_NO);
Таким образом, вы предоставляете простой API в виде создателей действий redux для управления состоянием вашего ModalWindow. Что вы можете позже использовать, например:
dispatch(showInformation())
...
dispatch(hideModal())
Конечно, это может быть что-то большее, например, дополнительная конфигурация, которая будет передана создателям действий или очередь для модальных окон.
Использование частей uikit, которые манипулируют dom (show, hide), очевидно, трудно соединить с React (и, вероятно, вам не следует этого делать), однако:
Вам нужно переместить вызов функций show и hide внутри компонента, передав логическое значение состояния модального окна (например, modalopen). Хороший крючок - componentWillReceiveProps, который можно использовать для проверки предыдущего реквизита.
componentWillReceiveProps(nextProps) {
if (nextProps.modalopen !== this.props.modalopen) {
if (nextProps.modalopen) {
getByName(...).show()
} else {
getByName(...).hide()
}
}
}
(это внутри модального класса)
Вы, вероятно, делаете что-то подобное для своего загруженного (предположение основано на showLoader и hideLoader в диспетчере)
работает ли состояние redux с этим? Можете ли вы добавить образец кода с вашими действиями redux.