React Redux在Modal中的使用

时间:2019-05-22 14:47:42

标签: reactjs redux react-redux

我正在React中学习Redux。我在React中使用Redux进行模态开发。我的代码如下所示

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>
    );
  }
}

(我是否正确使用<Provider store={store}>?)在子组件中,我无法使用Redux语法。就像我使用这个export default connect()(EditableRow);一样,我得到了错误(组件执行未在该组件上完成,需要执行)。如果我使用这种语法export default EditableRow;,则不会出现任何错误。

可能是我无法正确表达我的问题。

这是我的仓库https://github.com/afoysal/mern/blob/master/client/src/components/ModalBody.js

我遇到了错误。

enter image description here

如何在React Modal中使用Redux?

2 个答案:

答案 0 :(得分:3)

这里的问题来自使用React portals

  

门户提供了一种一流的方式来将子级呈现到父组件的DOM层次结构之外的DOM节点中。

Portal允许在另一个DOM下不渲染React元素。经过简化,这看起来像

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

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

因此,在ComponentA中,Provider不会看到ComponentB

您可能会看这个page,但是它并不能完全描述您遇到的问题。

如果查看<Modal>组件源,它将使用React.createPortal进行渲染并失去父级的提供者。

我看到一个解决方法

  1. 从合作伙伴的store中提取<Provider/>
  2. 在使用<Provider>之后立即创建新的<Modal>

    // 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>
    

答案 1 :(得分:1)

我希望你没有把所有东西都正确包装,
打包后,可在整个应用中访问,
如redux所述,必须有单一的真理来源,
一定要遵循原则。

// 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>

或尝试包装整个应用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')
)