使用无状态功能组件在react-redux中创建模态

时间:2017-02-16 07:55:59

标签: reactjs redux react-redux

我们正在React-Redux中实现一个应用程序,其中包含无状态功能组件和容器,用于需要处理状态的应用程序。我们的想法是将所有信息都存储在Redux商店中。

在应用程序中,我们需要在几个地方显示不同的模态窗口。我已经在堆栈溢出中查看了这里的文章,但我无法使其工作。我遵循了Dan Abramov在this post中描述的过程。

我的主要问题是我应该在我的应用程序中渲染我的ModalRoot组件。该过程如下:

  1. 我有一个按钮,可以调度动作displayModal以显示模态......

    clickHandler: modalProps => (
    dispatch(displayModal('MODAL_1', modalProps))
    
    export function displayModal(modalType, modalProps) {
      return {
        type: DISPLAY_MODAL,
        payload: {
          modalType,
          modalProps
        }
      };
    }
    
  2. 然后该操作由reducer处理,该reducer将modalType属性设置为redux-state ...

    export default function (modal = Map(), action) {
      if (!action) {
        return modal;
      }
      switch (action.type) {
        case DISPLAY_MODAL:
          return modal
            .set('modalType', action.payload.modalType)
            .set('modalProps', action.payload.modalProps);
        default:
          return modal;
      }
    }
    
  3. 然后我有ModalRootContainer将状态传递给我的ModalRoot组件......

    const mapStateToProps = state => (
      {
        modalType: modalState(state).get('modalType'),
        modalProps: modalState(state).get('modalProps')
      }
    );
    
    const ModalRootContainer =
      connect(mapStateToProps)(ModalRoot);
    
    export default ModalRootContainer;
    
  4. ModalRootComponent如下:

    const ModalRoot = (modalType, modalProps) => {
      if (!modalType) {
        return <span />;
      }
    
      switch (modalType) {
        case 'MODAL_1':
          return <MyComponent {...modalProps}/>;
        default:
          return <span />;
      }
    };
    
    ModalRoot.propTypes = {
      modalType: PropTypes.string,
      modalProps: PropTypes.object
    };
    
    export default ModalRoot;
    
  5. 我的理解是这是正确的,但它不起作用。 ModalRoot应该放在哪里?在Provider标签内?我错过了什么?

    修改1 : 我试图使用随机用户在下面的答案中说的没有效果。所以我在我的index.html:

    <body>
    <div id="modals"></div>
    <div id="root"></div>
    </body>
    

    在我的main.js中:

    ReactDOM.render(
          <Provider store={store}>
            <Router history={hashHistory}>{routing(store)}</Router>
          </Provider>,
          document.getElementById('root')
        );
        ReactDOM.render(
          <Provider store={store}>
            <ModalRootContainer />
          </Provider>,
          document.getElementById('modals')
        );
    

    使用上述所有设置仍然没有显示模态。我调试,我看到操作被触发,状态从reducer更新。有没有办法在这一点之后调试以查看我的容器是否有问题以及为什么模态没有显示?

    编辑2 :我发现了什么问题。我错误地把状态传给了我的容器。代码似乎工作,但现在,而不是有一个模态窗口显示,我有我的组件(应该在模态内)出现在我的剩余页面上方。我只是渲染一个简单的文字&#34;关闭模式&#34;和一个关闭它的按钮。它被正确显示和隐藏,但它不能作为模态,它只是显示和隐藏。对我失踪的任何帮助?

    Hidden:

    Shown:

2 个答案:

答案 0 :(得分:1)

您应该在当前ModalRootContainer内呈现Provider。你可能有一些app.js文件里面有<Provider> ... </Provider>。这是您应该渲染容器的地方。

这是因为redux通过上下文(https://facebook.github.io/react/docs/context.html)共享状态。 Provider是创建该上下文的组件,感谢connect您在props中拥有其数据。因此,要访问state,必须将所有容器渲染为Provider组件的子/孙/ ...

答案 1 :(得分:1)

您已声明ModalRootComponent但要实际使用它,您必须在应用程序中的某处呈现它。我的意思是渲染是将其置于反应ReactDOM.render(...)函数中。

当你使用redux时,渲染函数通常看起来像这样,Provider标记在所有内容之上:

ReactDOM.render(
  <Provider store={store}>

    ...

  </Provider>,
  document.getElementById('root')
);

如何渲染ModalRootContainer组件只是将它放在Provider标记中,如下所示:

ReactDOM.render(
  <Provider store={store}>

    <ModalRootContainer />

  </Provider>,
  document.getElementById('root')
);

但是在更复杂的情况下,您可以在这里渲染路由器,然后在每条路线中实际执行内容:

ReactDOM.render(
  <Provider store={store}>

    <Router history={history}>
      {routes}
    </Router>

  </Provider>,
  document.getElementById('root')
);

还要确保您已正确设置redux存储,并且它知道您的减速器。您可以使用react和redux here查看工作todo示例。