问题
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
- Extract
storefrom partner's<Provider/> 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