问题
I have a react-modal which shows some filters. It accepts an isOpen
prop which hides or shows the Modal as per the value.
The Modal
opens successfully when clicked on 'Apply' button, but does not close on clicking 'Cancel'.
//Click Handlers in the parent component (filters.js)
openAllFilters = () => {
this.setState({ showAllFilters: true });
};
closeAllFilters = () => {
this.setState({ showAllFilters: false }, () =>
console.log("state ", this.state.showAllFilters)
); // logs true!);
};
<AllFilters isOpen={this.state.showAllFilters}
closeAllFilters={this.closeAllFilters}
onRequestClose={this.closeAllFilters}
renderAbcFilter={this.renderAbcFilter}
renderDefFilter={this.renderDefFilter}
renderXyzFilter={this.renderXyzFilter}
/>
The Modal component (AllFilters.js):
import React from 'react';
import Modal from 'react-modal';
const RenderFilter = props => {
return <div className="filter-wrapper">
<h3 className="filter-title">{props.title}</h3>
{props.renderFunction()}
</div>;
}
const AllFilters = (props) => {
const modalStyles = {
overlay: {
zIndex: 200,
},
content: {
top: '0',
left: '0',
right: '0',
bottom: '0',
padding: '0',
}
};
return (
<Modal isOpen={props.isOpen}
style={modalStyles}
onRequestClose={props.closeAllFilters}>
<div className="all-filters-container">
<RenderFilter title='ABC' renderFunction={() => props.renderAbcFilter(false)} />
<RenderFilter title='XYZ' renderFunction={() => props.renderXyzFilter(false)} />
<RenderFilter title='DEF' renderFunction={() => props.renderDefFilter(false)} />
</div>
<div className="all-filters-footer">
<button className="button button-secondary filter-cancel-btn " onClick={props.closeAllFilters}>CANCEL</button>
</Modal >
)
}
export default AllFilters;
I can't figure out why state
is not updated to false
when closeAllFilters
is called?
EDIT: closeAllFilters
does get called when 'Cancel' button is clicked. And console.log(this.state.showAllFilters)
outputs true
!. Even though this is the setState
callback!
EDIT2 : I figured that openAllfilters
is somehow automatically getting called after closeAllFilters
is invoked. Thus it sets showAllFilters
back to true
and the modal remains open. Have updated the question title to better reflect the issue. The stack trace for the same is as follows:
openAllFilters (filters.js#382)
callCallback (react-dom.development.js#149)
invokeGuardedCallbackDev (react-dom.development.js#199)
invokeGuardedCallback (react-dom.development.js#256)
invokeGuardedCallbackAndCatchFirstError (react-dom.development.js#270)
executeDispatch (react-dom.development.js#561)
executeDispatchesInOrder (react-dom.development.js#580)
executeDispatchesAndRelease (react-dom.development.js#680)
executeDispatchesAndReleaseTopLevel (react-dom.development.js#688)
forEachAccumulated (react-dom.development.js#662)
runEventsInBatch (react-dom.development.js#816)
runExtractedEventsInBatch (react-dom.development.js#824)
handleTopLevel (react-dom.development.js#4826)
batchedUpdates$1 (react-dom.development.js#20439)
batchedUpdates (react-dom.development.js#2151)
dispatchEvent (react-dom.development.js#4905)
1 (react-dom.development.js#20490)
unstable_runWithPriority (scheduler.development.js#255)
interactiveUpdates$1 (react-dom.development.js#20489)
interactiveUpdates (react-dom.development.js#2170)
dispatchInteractiveEvent (react-dom.development.js#4882)
From above call stack, it seems that React is somehow triggering openAllFilters
. I went through these function calls one by one, but still can't figure out why it's happening. Maybe someone who understands React source code well might be able to offer some insight..
回答1:
So after a lot of debugging and head scratching, I finally figured out what the issue was. openAllFilters
was getting invoked after call to closeAllFilters
due to event propagation. The event is triggered by clicking anywhere on the modal. I didn't find any prop to disable this behaviour, so maybe it's a bug of react-modal
. So the only fix required was to add e.stopPropagation()
!
So the changed method becomes:
closeAllFilters = (e) => {
this.setState({ showAllFilters: false });
e.stopPropagation();
}
Thanks for all the help though!
来源:https://stackoverflow.com/questions/57390304/react-dom-automatically-triggering-onclick-handler