UIkit在React中的模态:集成

Urs*_*sus 8 reactjs getuikit

我正在开发这个项目,其前端是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
  }
}
Run Code Online (Sandbox Code Playgroud)

这是以这种方式使用的

export const LoginFormModal = props => (
  <Modal name="login-form" className="login-form-modal" hideClose>
    <LoginForm />
  </Modal>
)
Run Code Online (Sandbox Code Playgroud)

在需要的地方以编程方式调用show/hide(甚至还原为redux)

Modal.hide("login-form")
Run Code Online (Sandbox Code Playgroud)

这是一个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())
      }
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

这似乎有效.直到你离开组件.当你回到它时,第二次以编程方式隐藏不再起作用.

任何人都可以引导我如何以更适合反应的方式整合零件?

Tom*_*zyk 2

我不喜欢并且绝对不是“React-way”的事情是代码直接从动作创建者改变状态(!)。来自反应文档

例如,不要在 Dialog 组件上公开 open() 和 close() 方法,而是向其传递 isOpen 属性。

那么如果你有一个由 redux 状态控制的模态呢?这是一个可能的实现:

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);
Run Code Online (Sandbox Code Playgroud)

模态减速器它将公开 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);
Run Code Online (Sandbox Code Playgroud)

所以基本上你以 redux action-creators 的形式公开简单的 API 来控制ModalWindow. 您稍后可以使用它,例如:

dispatch(showInformation())
...
dispatch(hideModal())
Run Code Online (Sandbox Code Playgroud)

当然,可能还有更多内容,例如传递给动作创建者或模态队列的可选配置。