Reputation: 69
I'm not sure if this has been asked before. I couldn't find anything after googling.
I have a parent component which basically has a button which when clicked will open a modal.
Inside the modal, there is a form which makes a post-call to an API. If the post-call is successful, I need the modal to be closed. I'm experimenting custom hooks to achieve this.
Below is my code:
Custom Hook
type savedHook = {
saved: boolean,
loading: boolean,
error: string,
saveSearch: (search: any) => void,
showNewModal: boolean,
setShowNewModal: (boolean) => void
};
export const useSaveSearch = () : savedSearchHook => {
const [loading, setLoading] = useState(false);
const [saved, setSaved] = useState(false);
const [error, setError] = useState('');
const [showNewSaveSearch, setNewShowSearch] = useState(false);
const saveSearch = async (search: any) => {
setLoading(true);
fetch('my api', {
method: 'POST',
body: JSON.stringify(search),
headers: {
'Content-Type': 'application/json'
}
}).then((data) => {
setSaved(true);
setLoading(false);
setShowNewModal(false);
}).catch((error) => {
setError(error);
setLoading(false);
});
}
const setShowNewModal = (show: boolean) => {
setNewShowSearch(show);
}
return {
error,
loading,
saveSearch,
saved,
setShowNewModal,
showNewModal: showNewSaveSearch
}
}
Modal
export default function SaveSearch({isOpen, onDismiss}) {
const { state } = useSearch();
const [name, setName] = useState('');
const { loading, saved, error, saveSearch } = useSaveSearch();
const handleSave = () => {
saveSearch({
name,
query: state.query,
type: state.type
});
}
return (
<Modal isOpen={isOpen} onDismiss={onDismiss}>
<div>
<span>Save Search ({state.type})</span>
<IconButton styles={iconButtonStyles} iconProps={{iconName: 'Cancel'}} onClick={onDismiss} />
</div>
<div>
<TextField label="Name" autoFocus value={name} onChange={(e, value) => setName(value)} />
{loading && <Spinner size={SpinnerSize.small} />}
<DefaultButton text="Save" onClick={handleSave} iconProps={{iconName: 'Save'}} disabled={name.length === 0 || loading} />
</div>
</Modal>
)
}
Parent Component
export default function ParentComponent() {
const { showNewModal, setShowNewModal } = useSaveSearch();
return (
<div>
{<SaveSearch isOpen={showNewModal} onDismiss={() => setShowNewModal(false)} />}
<PrimaryButton text="Save Search" onClick={() => setShowNewModal(true)} iconProps={{iconName: 'Save'}} />
</div>
);
}
The problem I'm facing is, to open the modal, I'm calling setShowNewModal from the parent component which works fine. But after the save function, I'm calling setShowNewModal from the hook which doesn't get updated in the parent component.
Upvotes: 1
Views: 118
Reputation: 1768
It would be good if you could provide a working example.
Anyways, if I'm correct, the setShowNewModal(false);
inside the saveSearch
method of useSaveSearch
custom hook should close the Modal
, right?
Well, if that's the case, inside setShowNewModal
you just call setNewShowSearch
. Then, the value of setNewShowSearch
is returned for a property named showNewModal
, but inside the Modal
, when you write the following line:
const { loading, saved, error, saveSearch } = useSaveSearch();
You don't consider the showNewModal
property, in the deconstructor. Maybe I'm missing something in the flow: that's why I was asking for a working demo.
Anyways, going back to the issue: inside the Modal
component you could just pass the onDismiss
method:
const { loading, saved, error, saveSearch } = useSaveSearch(onDismiss);
And inside the useSaveSearch
custom hook, just call the onDismiss
parameter, which will call the callback () => setShowNewModal(false)
defined in the Parent
component.
Upvotes: 1