Here I am unable to click the button and open the dialog box once it has already been opened and to do so I need to go back and return or refresh the page. Initially the dialog box didn’t open after it has been opened once, I tried and debugged and not it is working ok for 2 times but the user is unable to change the location (via opening the dialog box) as many times as they want.
For the reference I am posting two code snippets HomeLocation/index.js and HomeLocationDialog/index.js
here is the code for HomeLocation/index.js
function HomeLocation({ onHomeLocationUpdated }) {
const [selectedLocation, updateLocation] = useState();
const [showDialog, setShowDialog] = useState(false);
const [progressBar, setProgressBar] = useState(true);
const [errorComponent, showErrorComponent] = useState(false);
const [shouldResetDialog, setShouldResetDialog] = useState(false);
useEffect(() => {
fetchHomeLocation();
}, []);
useEffect(() => {
onHomeLocationUpdated(selectedLocation);
}, [selectedLocation]);
const fetchHomeLocation = async () => {
setProgressBar(true);
showErrorComponent(false);
ShippingData.getShippingHomeLocation().then((data) => {
updateLocation(data);
}).catch(() => {
showErrorComponent(true);
}).then(() => {
setProgressBar(false)
});
}
const openDialog = () => {
setShowDialog(true)
setShouldResetDialog(true)
}
const closeDialog = () => {
setShowDialog(false)
}
return <div className='shippingItemContainer shippingHomeCityContainer' onClick={openDialog}>
<CustomLabel value={'Home city'} />
{
progressBar ? <CircularProgress size={24} color="primary" style={{ marginTop: '8px' }} /> :
errorComponent ? <CustomErrorComponent onRetryClick={fetchHomeLocation} /> : <div className='updateCityContainer'>
{(selectedLocation || {}).name && <span className='city'>{selectedLocation.name}</span>}
<ChangeText text={isNil((selectedLocation || {}).name) ? 'Select' : 'Change'} onClick={openDialog} />
</div>
}
{showDialog && <HomeLocationDialog
showDialog={shouldResetDialog}
onClose={closeDialog}
onSuccess={(location) => {
updateLocation(location);
setShouldResetDialog(false);
}}
/>}
</div>
}
export default withRouter(HomeLocation);
HomeLocationDialog/index.js
export default function ({ showDialog, onClose, onSuccess }) {
const noResultTextWhenCharLessThanThree = 'Type full city name';
const noResultText = 'No results found.';
const [cities, setCities] = useState([]);
const [updatedLocation, setUpdatedLocation] = useState(null);
const [progressBar, setProgressBar] = useState(false);
const [loadingData, setLoadingData] = useState(false);
const [closeDialog, setCloseDialog] = useState(false);
const [errorMessage, setErrorMessage] = useState(null);
const [noOptionText, setNoOptionText] = useState(noResultTextWhenCharLessThanThree);
const [shouldResetDialog, setShouldResetDialog] = useState(false);
useEffect(() => {
if (showDialog && shouldResetDialog) {
setShouldResetDialog(false);
}
}, [showDialog,shouldResetDialog]);
const handleHomeLocationChange = (event, values) => {
setUpdatedLocation(values);
};
const fetchCities = async (e) => {
const content = (e.target.value).trim();
if (!isNil(content) && content.length > 2) {
setErrorMessage(null);
setLoadingData(true);
ShippingData.getAllCities(e.target.value).then((allCities) => {
const sortedCities = sortBy(allCities, o => o.name);
if (sortedCities.length === 0) {
setNoOptionText(noResultText);
}
setCities(sortedCities);
}).catch((err) => {
onApiFailure(err)
}).then(() => {
setLoadingData(false)
});
} else {
setNoOptionText(noResultTextWhenCharLessThanThree);
setCities([]);
}
}
const updateHomeCity = async () => {
setProgressBar(true);
setErrorMessage(null);
setUpdatedLocation(updatedLocation);
ShippingData.updateShippingHomeLocation({ cityId: updatedLocation.cityId }).then(() => {
CacheRequest.deleteCacheForKeys([CacheKeys.shippingZonesCacheKey]);
onApiSuccess();
setShouldResetDialog(true);
}).catch((err) => {
onApiFailure(err)
}).then(() => {
setProgressBar(false)
});
}
const onApiSuccess = () => {
setCloseDialog(true);
onSuccess(updatedLocation);
}
const onApiFailure = (error) => {
setErrorMessage(error);
}
return showDialog && <DialogBox
type={"simple"}
dialogId={'#select-city'}
show={showDialog}
width={300}
primaryBtnText={'SAVE'}
onSuccess={updateHomeCity}
onClose={onClose}
disabledPrimaryButton={isNil(updatedLocation)}
showProgressBar={progressBar}
closeDialog={closeDialog}
>
<Fragment>
<div className='cityDialogContent'>
<p className='dialogTitle'>Select city</p>
<Autocomplete
loading={loadingData}
noOptionsText={noOptionText}
onChange={handleHomeLocationChange}
id="autocomplete-city-select"
options={cities}
getOptionLabel={(option) => option.name + ', ' + option.state}
renderInput={(params) => <TextField
onChange={fetchCities}
autoFocus {...params}
placeholder={'Type atleast 3 characters'}
margin="normal"
InputProps={{
...params.InputProps,
endAdornment: (
<React.Fragment>
{loadingData ? <CircularProgress color="inherit" size={18} /> : null}
{params.InputProps.endAdornment}
</React.Fragment>
),
}} />}
/>
{errorMessage && <CustomErrorComponent errorMessage={errorMessage} />}
</div>
</Fragment>
</DialogBox>
}
I almost tried to debug it for not less than 10 hours but couldn’t solve it, thanks in advance. point out the logical error and help me solve this.
2
Answers
If I understood correctly you’re only hiding the contents of the child by having conditional rendering there. You never call
onClose
so the parent doesn’t know it was closed. Basically you only hide the contents but the dialog stays open.Remove the
showDialog
from the child, it should not do that. Only parent should control if it’s shown. Then callonClose
from the child when it’s closed so the parent actually gets information that it should be closed and can hide it.After this the parent actually controls the child correctly.
<HomeLocation />
have root wrapper<div className='shippingItemContainer shippingHomeCityContainer' onClick={openDialog}>
by each click by all over inside
openDialog
handler will be called and open your dialog.