Usage of React Redux in Modal

允我心安 提交于 2020-04-14 05:56:40

问题


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.

How to use Redux in React Modal ?


回答1:


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>
    



回答2:


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')
)


来源:https://stackoverflow.com/questions/56259508/usage-of-react-redux-in-modal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!