skip to Main Content

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


  1. 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 call onClose 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.

    Login or Signup to reply.
  2. <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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search