在React / Redux应用程序中正确隔离组件,但允许在彼此之间传递回调

时间:2017-07-31 07:45:13

标签: reactjs ecmascript-6 redux react-redux

我刚开始学习与Redux的React,所以请宽容。 我跟着Redux开始了,到目前为止,这么好。但是沿着'基本'和'高级'redux doc部分,我结束了我所有组件都被隔离的位置。这完全没问题。除了我的一个组件旨在显示通知,解雇并删除它们。 另一个是需要4个参数才能工作的模态:一个带有标题文本部分,一个用于正文,另一个用于设置是否显示,另一个用于在单击确认按钮时触发确认操作。 当用户想要删除通知时,我的通知组件需要显示模式。两个组件都使用redux处理状态。

以下是一些内容。

下面是notification reducer,它处理dismissing删除和获取通知。很简单。

// The notifications reducer
let initialState = {
  isFetching: false,
  didInvalidate: false,
  notifications: []
}

const notifications = (state = initialState, action) => {
  switch (action.type) {
    case 'DISMISS':
      return {...state, notifications: state.notifications.map(element => element.id === action.id ? {...element, dismissed: !element.dismissed} : element)}
    case 'DISMISS_ALL':
      return {...state, notifications: state.notifications.map(element => { return {...element, dismissed: false} }) }
    case 'DELETE':
      return {...state, notifications: state.notifications.filter(element => element.id !== action.id)}
    case 'DELETE_ALL':
      return {...state, notifications: []}
    case 'INVALIDATE':
      return {...state, didInvalidate: true}
    case 'REQUEST':
      return {...state, isFetching: true, didInvalidate: false}
    case 'RECEIVE':
      return {...state, isFetching: false, didInvalidate: false, notifications: action.posts, lastUpdate: action.receivedAt}
    default:
      return state
  }
}

export default notifications

然后是通知操作。这里的重点是deleteNotificationdeleteAllNotifications动作,它们必须绑定模态开口并等待其响应,然后触发删除,并且仅在此之后。 那些人需要(我猜测)像fetchNotifications动作一样工作,调用另一个动作(模态的一个),而不是像fetchNotifications一样进行数据提取。

// The notifications actions
//@flow
import axios from 'axios'

/**
 * NOTIFICATIONS ACTION CREATORS
 */
export const dismissNotification = (id: number) => {
  return { type: 'DISMISS', id }
}
export const dismissAllNotifications = () => {
  return { type: 'DISMISS_ALL' }
}
export const deleteNotification = (id: number) => {
  return { type: 'DELETE', id }
}
export const deleteAllNotifications = () => {
  return { type: 'DELETE_ALL' }
}

/**
 * DATABASE NOTIFICATIONS ACTION CREATORS
 */
export const invalidate = (uri: string) => {
  return { type: 'INVALIDATE', uri }
}
export const requestNotifications = (uri: string) => {
  return { type: 'REQUEST', uri }
}
export const receiveNotifications = (uri: string, json: string) => {
  return {
    type: 'RECEIVE',
    uri,
    posts: json,
    receivedAt: Date.now()
  }
}
export const fetchNotifications = (uri: string) => {
  return (dispatch: any) => {
    dispatch(requestNotifications(uri))
    return axios.get(uri)
      .then(
        response => response.data,
        error => console.log('Error', error) // TODO logger les erreurs
      )
      .then(json => {
        dispatch(receiveNotifications(uri, json))
      })
  }
}

最后,模态的减速器。减速器的要点是通过headerMessagebodyMessage来处理显示(可见或不可见),文本。 id在这里告诉模态是否必须在一个signle元素或一大堆元素上发送一个删除。这对我来说很脏。它应该只返回一个确认,例如,作为响应将被通知操作捕获的确认。

let initialState = {
  showModal: false,
  headerMessage: '',
  bodyMessage: '',
  id: false
}

const modal = (state = initialState, action) => {
  switch (action.type) {
    case 'MODAL_DISPLAY':
      return {...state,
        showModal: action.showModal,
        headerMessage: action.headerMessage,
        bodyMessage: action.bodyMessage,
        id: action.id
      }
    case 'MODAL_HIDE':
      return {...state,
        showModal: action.showModal,
        headerMessage: action.headerMessage,
        bodyMessage: action.bodyMessage,
        id: action.id
      }
    default:
      return state
  }
}

export default modal

为了清楚起见,模态组件和通知组件位于不同的目录中。我希望模态组件可以在任何上下文中使用。这是关于通知的,但是如果我希望它与除通知之外的任何其他组件一起工作,让我们说用户的配置文件,我不应该专门与任何组件绑定。

在我的例子中,notification组件是调用模态的组件。这就是“驱动”全球行为。但我想我并没有很好地建立这一切。这是我的通知组件索引:

//@flow

import React from 'react'
import { render } from 'react-dom'
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger'
import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose } from 'redux'
import { fetchNotifications } from './store/actions/NotificationsActions'
import NotifiationsApp from './store/reducers/reducerCombiner'
import App from './components/App'
import ModalContainer from '../modal-component/store/containers/ModalContainer'

const loggerMiddleware: any = createLogger()
const composeEnhancers: any = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
const store: any = createStore(
  NotifiationsApp,
  composeEnhancers(
    applyMiddleware(
      thunkMiddleware,
      loggerMiddleware
    )
  )
)

store.dispatch(fetchNotifications('/app_dev.php/notifications/load?offset=0&limit=10'))

render(
  <Provider store={store}>
    <div>
      <App/>
      <ModalContainer />
    </div>
  </Provider>,
  document.getElementById('notifications-component')
)

正如你所看到的,我正在调用事实上的ModalContainer,即'智能'模态组件抽象。 最后,这是我的坏事;将ModalContainer绑定到通知组件的onConfirm,我希望在import { connect } from 'react-redux' import { deleteAllNotifications, deleteNotification } from '../../../notifications-component/store/actions/NotificationsActions' import { hideModal } from '../actions/ModalActions' import ModalInstance from '../../components/Modal' const getModalProperties = modal => { return modal } const mapStateToProps = state => { return getModalProperties(state.modal) } const mapDispatchToProps = dispatch => { return { onCancel: () => { dispatch(hideModal(false, false, '', '')) }, onConfirm: id => { // BELOW, THIS IS VERY BAD!! id ? dispatch(deleteNotification(id)) : dispatch(deleteAllNotifications()) dispatch(hideModal(false, '', '', false)) } } } const ModalDisplay = connect( mapStateToProps, mapDispatchToProps )(ModalInstance) export default ModalDisplay 被触发时“返回”确认事件:

M2_Home: C:\Program Files\apache-maven-3.5.0 (I already tried it with \bin didn't work ether.)

我在这个问题上挣扎。请帮助!

2 个答案:

答案 0 :(得分:0)

我不确定自己是否理解正确,但似乎您正在寻找ownProps。您希望将函数传递给ModalWindow组件,该组件将在调用确认函数后调用,对吗?这样你就有了像

这样的界面
<ModalContainer onConfirm={myHandler}/>

在这种情况下,您的mapDispatchToProps需要考虑传递给容器的道具,例如

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    onCancel: () => {
      dispatch(hideModal(false, false, '', ''))
    },
    onConfirm: id => { // BELOW, THIS IS VERY BAD!!
      id ? dispatch(deleteNotification(id)) : dispatch(deleteAllNotifications())
      dispatch(hideModal(false, '', '', false));
      ownProps.onConfirm && ownProps.onConfirm(id);
    }
  }
}

答案 1 :(得分:0)

你一般都在正确的轨道上。方便的是,我刚刚发布了Practical Redux, Part 10: Managing Modals and Context Menus,它演示了如何使用Redux构建和控制模态,上下文菜单和通知。这包括如何处理&#34;返回值&#34;来自模态,因为他们已经关闭。

要专门回答您的问题:清除一个通知的ID与所有通知的处理并不会显得很糟糕&#34;脏&#34;或者&#34;坏&#34;对我来说 - 这种方法应该没问题。