react-dynamic-modal icon indicating copy to clipboard operation
react-dynamic-modal copied to clipboard

How to use with styled-components ?

Open kopax opened this issue 7 years ago • 1 comments

I am using styled-components 2.0.0-4. This library allow you to create React component that include their css.

It's also possible to use a ThemeProvider in order to modify the theme passed to sub components.

Unfortunallety, this doesn't work fine with react-dynamic-modal

I have created the following class :

import React, { PropTypes } from 'react';
import { Modal as ReactDynamicModal, ModalManager } from 'react-dynamic-modal';
import Effect from './Effect';
import Button from '../Button';

const defaultProps = {
  close: true,
};

class Modal extends React.Component {

  static propTypes = {
    effect: PropTypes.object,
    close: PropTypes.oneOfType([
      PropTypes.bool,
      PropTypes.string,
    ]),
    children: PropTypes.node,
    onRequestClose: PropTypes.func,
  }

  render(){
    const { children, effect, onRequestClose, close, ...rest } = this.props;
    return (
      <ReactDynamicModal
        onRequestClose={onRequestClose}
        effect={effect || Effect.None}
        {...rest}
      >
        {children}
        {close && <Button className="btn-primary" onClick={ModalManager.close}>{typeof close === 'string' ? close : 'Close' }</Button>}
      </ReactDynamicModal>
    );
  }
}

Modal.defaultProps = defaultProps;

export default Modal;

This work fine, but for some reason, when trying to use withTheme when doing export default withTheme(modal) in order to have access to this.props.theme within the render method.

For some reason I don't know yet, this doesn't work in your library.

I have the following message : [withTheme] Please use ThemeProvider to be able to use withTheme

My whole app is wrapped around a <ThemeProvider theme={theme}>, so I guess react-dynamic-modal does something unconventional. (By modifying the DOM somehow).

Do you have an idea what is happening with your lib ?

kopax avatar Mar 01 '17 04:03 kopax

It appear this is due to the fact that the component is injected beside the highest react component in DOM which is for me the


const render = (messages) => {
  ReactDOM.render(
    <Provider store={store}>
      <LanguageProvider messages={messages}>
        <ThemeProvider
          theme={{
            '$btn-primary-bg': 'red',
          }}
        >
          <Router
            history={history}
            routes={rootRoute}
            onUpdate={hashLinkScroll}
            render={
              // behaviour
              applyRouterMiddleware(useScroll())
            }
          />
        </ThemeProvider>
      </LanguageProvider>
    </Provider>,
    document.getElementById('app')
  );
};

This means I can't connect my modal to my redux-store , react-i18n and styled-component because this component is out of context which is a huge limitation.

Would be nice to allow it's injection within the <App /> as an HoC instead of automatic injection.

export default (App) => class AppWithModal extends React.Component {

  render() {
    return `
      <div>
         <Modal />
         {this.props.children}
      </div>
    `;
  }

}

kopax avatar Mar 01 '17 09:03 kopax