Как обновить родительский компонент с состоянием, которое было обновлено в пользовательском хуке? - PullRequest
1 голос
/ 07 мая 2020

Я не уверен, спрашивали ли об этом раньше. Я не смог ничего найти после поиска в Google.

У меня есть родительский компонент, который в основном имеет кнопку, при нажатии на которую открывается модальный.

Внутри модального окна есть форма, которая делает пост-вызов API. Если пост-вызов прошел успешно, мне нужно закрыть модальное окно. Я экспериментирую с пользовательскими хуками, чтобы добиться этого.

Ниже мой код:

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>
    )
  }

Родительский компонент

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>
   );
}

Проблема, с которой я столкнулся, заключается в том, чтобы открыть модальное окно, я вызываю setShowNewModal из родительского компонента, который работает отлично. Но после функции сохранения я вызываю setShowNewModal из хука, который не обновляется в родительском компоненте.

1 Ответ

1 голос
/ 07 мая 2020

Было бы хорошо, если бы вы могли предоставить рабочий пример.

В любом случае, если я прав, setShowNewModal(false); внутри метода saveSearch пользовательского хука useSaveSearch должен закрыть Modal, верно?
Ну, если это так, внутри setShowNewModal вы просто звоните setNewShowSearch. Затем значение setNewShowSearch возвращается для свойства с именем showNewModal, но внутри Modal, когда вы пишете следующую строку:

const { loading, saved, error, saveSearch } = useSaveSearch();

Вы не учитываете showNewModal свойство в деконструкторе. Может быть, мне чего-то не хватает в потоке: вот почему я просил рабочую демонстрацию.

В любом случае, возвращаясь к проблеме: внутри компонента Modal вы можете просто передать метод onDismiss:

const { loading, saved, error, saveSearch } = useSaveSearch(onDismiss);

И внутри настраиваемой ловушки useSaveSearch просто вызовите параметр onDismiss, который вызовет обратный вызов () => setShowNewModal(false), определенный в компоненте Parent.

...