Обновление данных, полученных с помощью настраиваемой ловушки, после закрытия модального окна

Я использую ловушку для получения данных в своем приложении. Крючок выглядит примерно так:

const initialState = {
  response: null,
  loading: true,
  error: null
}
const useGetFetch(url, token, user, parser) => {
  const [state, dispatch] = useReducer(fetchReducer, initialState)

  useEffect (() => {
    if(user){
      fetch(...)
      .then((data)=> data.json())
      .then(dispatch(...)) // setting the state here
      .catch((error) => dispatch(...)) // set error state
    }
  }, [user])

 return [state.response, state.loading, state.error]
}

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

Однако мне нужно позволить пользователю добавлять новые параметры на лету. Чтобы облегчить это, я создал кнопку рядом с элементом выбора. Если пользователь нажмет эту кнопку, появится модальное окно с другой формой, позволяющей создать новую опцию. Эта новая опция отправляется на сервер через почтовый запрос, и в случае успеха модальное окно закрывается.

Проблема, с которой я столкнулся, заключается в том, что после закрытия модального окна у меня нет возможности обновить исходные данные, полученные с помощью моего обработчика выборки данных, если я не обновлю страницу. Есть ли способ как-то сделать это, не вызывая обновления страницы?

Моя первоначальная догадка заключалась в том, чтобы использовать функцию обратного вызова, передать ее в useGetFetch и привязать к хуку useEffect. Затем я мог бы передать его в форму в модальном окне и вызвать функцию после успешной отправки, но это не сработало.

Другой вариант, который я ищу, - это крючок useCallback, но в настоящее время я недостаточно хорошо его понимаю, чтобы знать, может ли он быть полезным.

ИЗМЕНИТЬ

В частности, я создал функцию триггера вне родительского компонента:

const trigger = () => console.log("click")

Привяжите его к крючку извлечения:

const useGetFetch(url, token, user, parser, trigger) => {
  const [state, dispatch] = useReducer(fetchReducer, initialState)

  useEffect (() => {
    if(user){
      fetch(...)
      .then((data)=> data.json())
      .then(dispatch(...)) // setting the state here
      .catch((error) => dispatch(...)) // set error state
    }
  }, [user, trigger])

 return [state.response, state.loading, state.error]
}

И передал его дочернему компоненту внутри родительского компонента:

const trigger = () => console.log("click")
const Parent = () => {
  // load a bunch of stuff
  // ...
    const { show, toggle } = useModal()

    const [optionsData, Loading, Error] = useGetFetch(
      optionsUrl,
      token,
      user,
      parser,
      trigger
  )
  // ...
  return (
    <div>
      {// ...}
      <button
              onClick={(e) => {
                e.preventDefault()
                toggle()
              }}
            >
              Add
            </button>
            <Modal show={show} toggle={toggle}>
              <ModalForm
                show={show}
                toggle={toggle}
                trigger={trigger}
              ></ModalForm>
            </Modal>
           {// ...}
    <div>
  )
}

Внутри ModalForm триггер вызывается после успешного выполнения почтового запроса. После закрытия модального окна данные не обновляются. Я предполагал, что триггер вызова внутри ModalForm сработал бы useEffect внутри useGetFetch, но, похоже, он так не работает.


person P4nd4b0b3r1n0    schedule 24.06.2020    source источник
comment
Хорошо, насколько я понял, проблема в том, что вы хотите восстановить данные, когда пользователь закрывает модальное окно? я прав?   -  person Anurag Hazra    schedule 24.06.2020
comment
Да, ты прав.   -  person P4nd4b0b3r1n0    schedule 24.06.2020


Ответы (2)


Если, если вы правильно поняли ваш вопрос, я думаю, что вы пытаетесь сделать повторную выборку всякий раз, когда пользователь закрывает модальное окно.

Вы можете сделать это, запустив принудительный рендеринг внутри хука useGetFetch, как показано ниже:

const useGetFetch(url, token, user, parser) => {
  const [state, dispatch] = useReducer(fetchReducer, initialState)
  // calling refetch will force a rerender on the hook
  const [shouldRefetch, refetch] = useState({}); 

  useEffect (() => {
    if(user){
      fetch(...)
      .then((data)=> data.json())
      .then(dispatch(...)) // setting the state here
      .catch((error) => dispatch(...)) // set error state
    }
  }, [user, shouldRefetch]); // note the dep array

 // returning the refetch functions so we can call the refetch() on modal close.
 return [state.response, state.loading, state.error, refetch];
}

И это все для useGetFetch, теперь вы будете использовать крючок следующим образом: -

const Parent = () => {
  const { show, toggle } = useModal();

  // notice the refetch method
  const [optionsData, Loading, Error, refetch] = useGetFetch(
    optionsUrl,
    token,
    user,
    parser
  );

  return (
    <div>
      <button
        onClick={e => {
          e.preventDefault();
          toggle();
        }}
      >
        Add
      </button>
      <Modal show={show} toggle={toggle}>
        <ModalForm
          show={show}
          toggle={toggle}
          trigger={() => {
            // probably onClose would be better name instead of `trigger`

            // calling the refetch method with empty object, this will cause rerender
            refetch({});
          }}
        ></ModalForm>
      </Modal>
    </div>
  );
};
person Anurag Hazra    schedule 24.06.2020
comment
Добро пожаловать, рады помочь: D - person Anurag Hazra; 24.06.2020

Я думаю, вам не хватает , внутри функции useEffect, поэтому вы получаете X не является функцией Ошибка

  useEffect (() => {
    if(user){
      fetch(...)
      .then((data)=> data.json())
      .then(dispatch(...)) // setting the state here
      .catch((error) => dispatch(...)) // set error state
    }
 //comma here
  },[user]);
person Ahmed Magdy    schedule 24.06.2020
comment
Я обновил свой вопрос, чтобы отразить это. Теперь функция распознается и вызывается, но не запускает обновление на крючке. - person P4nd4b0b3r1n0; 24.06.2020