4

I am learning Redux in React. I am using Redux in React for Modal development. My code is like below

render() {
    return (
      <Modal id="addressModal" open={this.props.controlModal} onClose={this.props.action}>
        <Provider store={store}>
          {this.props.addresObj ? (
            <Modal.Header>Address Details</Modal.Header>
          ) : (
            <Modal.Header>Insert Address</Modal.Header>
          )}
          <Modal.Content>
              <ModalElement
                update={this.update}
                element={this.props.addresObj}
                errors = {this.state.errors}
                update_state_photo={this.update_state_photo}
                address={this.props.address}
                action={this.props.action}
              />
          </Modal.Content>

          <Modal.Actions>
            {this.props.addresObj ? (
              <Button
                positive
                icon="checkmark"
                labelPosition="right"
                onClick={this.closeModal}
                content="OK"
              />
            ) : (
              <Button
                positive
                icon="checkmark"
                labelPosition="right"
                onClick={this.insertAddress}
                content="Save"
              />
            )}
          </Modal.Actions>
        </Provider>
      </Modal>
    );
  }
}

(Did I use <Provider store={store}> properly ?) In child component I can't use Redux syntax. Like if I use this export default connect()(EditableRow); I am getting error (component execution is not finish at that component, execution forwared). If I use this syntax export default EditableRow; I am not getting any error.

May be I could not express my issue properly.

Here is my repo https://github.com/afoysal/mern/blob/master/client/src/components/ModalBody.js

I am getting below error.

enter image description here

How to use Redux in React Modal ?

3
  • 2
    Where do you import Modal ? You created that component or is a third party library? Commented May 22, 2019 at 14:50
  • Thanks @Vencovsky. I created component. Commented May 22, 2019 at 14:52
  • 1
    want to put everything wrap inside <Provider store={}> Commented May 31, 2019 at 8:49

2 Answers 2

7

The problem here arise from using React portals

Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.

Portal allows to render React elements under another DOM none. With simplifications this will look like

const ComponentA = ReactDOM.createPortal(
    <CoolComponent />,
    document.getElementById('banner'),
)

const ComponentB = ReactDOM.createPortal(
    <SuperCoolComponent />,
    document.getElementById('footer'),
)

So in gneral ComponentA will not see Provider of ComponentB.

You may look at this page, however it does not fully describe problem you faced.

If look to <Modal> component source, it uses React.createPortal to render itself and looses parent's provider.

One workaround I see

  1. Extract store from partner's <Provider/>
  2. Create new <Provider> just after <Modal> usage.

    // ModelBody.js
    import { Provider, ReactReduxContext } from 'react-redux';
    
    //...
    render() {
        return (
            <ReactReduxContext.Consumer>
                {((ctx) => (
                    <Modal id="addressModal" open={this.props.controlModal} onClose={this.props.action}>
                        <Provider store={ctx.store}>  /* make store available in Portal */
                            {this.props.addresObj ? (
                                <Modal.Header>Address Details</Modal.Header>
                            ) : (
                                <Modal.Header>Insert Address</Modal.Header>
                            )}
                        /* other code from Model.js */
                        </Provider>
                    </Modal>
               )).bind(this) // Dont forget to bind this
           }
       </ReactReduxContext.Consumer>
    
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks @Fyodor for your reply. Here is the repo github.com/afoysal/mern/blob/master/client/src/components/… . You can check.
How do you run this app? I've cloned your repo on Windows pc but cannot start it. I've reinstalled npm modules, but still have no luck
Thanks @Fyodor. I am using linux mint 19. I run project with npm run dev command like this i.sstatic.net/bLAtv.png. I need your help. Thanks.
Many Many Thanks @Fyodor. You are really genius. Your solution is working. Thanks and Thanks.
0

i hope you didn't wrap everything inside properly,
once wrapped, its accessible throughout the app,
as redux states there must be single source of truth,
do try to follow principles.

// ModelBody.js
import { Provider, ReactReduxContext } from 'react-redux';

//...
render() {
    return (

        <ReactReduxContext.Consumer>
            {((ctx) => (
         <Provider store={ctx.store}>
                <Modal id="addressModal" open={this.props.controlModal} onClose={this.props.action}>
                      /* make store available in Portal */
                        {this.props.addresObj ? (
                            <Modal.Header>Address Details</Modal.Header>
                        ) : (
                            <Modal.Header>Insert Address</Modal.Header>
                        )}
                    /* other code from Model.js */

                </Modal>
           </Provider>
           )).bind(this) // Dont forget to bind this
       }
   </ReactReduxContext.Consumer>

or try to wrap your whole app, index.jsx

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import rootReducer from './reducers'
import App from './components/App'

const store = createStore(rootReducer)

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

1 Comment

Thanks @Ashish Kamble. Your fist solution is not working. Second solution is not matching with my component. Did you check the repo of github ? github.com/afoysal/mern/blob/master/client/src/index.js

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.