关闭模式后刷新使用自定义挂钩获取的数据

P4n*_*1n0 5 javascript fetch reactjs react-hooks use-effect

我正在使用挂钩来获取应用程序中的数据。钩子看起来像这样:

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]
}
Run Code Online (Sandbox Code Playgroud)

具体来说,我在表单组件内使用此挂钩来获取一些数据以用作选择元素内的选项。

但是,我需要能够让用户动态添加新选项。为了促进这一点,我在选择元素旁边创建了一个按钮。如果用户按下此按钮,将弹出一个模式,其中包含另一个表单,可以创建新选项。这个新选项通过发布请求发送到服务器,如果成功,模式将关闭。

我面临的问题是,模式关闭后,我无法更新使用自定义数据获取挂钩获取的初始数据,除非刷新页面。有没有办法让这种情况发生而不触发页面刷新?

我最初的预感是使用回调函数并将其传递给useGetFetch并将其绑定到useEffect钩子。然后,我可以将其传递给模式中的表单,并在成功提交后调用该函数,但这不起作用。

我正在寻找的另一个选择是钩子useCallback,但我目前对它的理解还不够好,不知道它是否有帮助。

编辑

具体来说,我所做的是在父组件外部创建一个触发器函数:

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

Run Code Online (Sandbox Code Playgroud)

将其绑定到 fetch hook:

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]
}
Run Code Online (Sandbox Code Playgroud)

并将其传递给父组件内的子组件:

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>
  )
}
Run Code Online (Sandbox Code Playgroud)

ModalForm成功执行 post 请求后调用内部触发器。关闭模态后,数据不会更新。我的猜测是,在内部调用触发器会在内部ModalForm触发,但它似乎并不像那样工作。useEffectuseGetFetch

小智 4

如果清楚地理解你的问题,我认为你想要做的是每当用户关闭模式时强制重新获取。

您可以通过在钩子内触发强制重新渲染来做到这一点,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];
}
Run Code Online (Sandbox Code Playgroud)

这就是 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>
  );
};
Run Code Online (Sandbox Code Playgroud)