使用React钩子的后台服务

时间:2019-08-11 09:23:51

标签: reactjs react-hooks

我有一个方案,其中后台服务必须定期调用其余服务。通过上下文中存储的状态确定服务必须运行的条件。我想知道最好的方法是创建/实例化此后台服务。鉴于该服务使用钩子,因此它必须位于组件中。

鉴于以下简化的结构,我希望将服务添加到MyContext元素中。但是,鉴于服务组件未返回任何内容,React给了我以下错误“ JSX元素类型'void'不是JSX元素的构造函数”-这对我来说很有意义。

<app>
 <MyContext>
  <MyBackgroundService />
  <MyUi />
 </MyContext>
</app>

我不想将所有子组件都包装到MyBackgroundService元素中。理想情况下,代码应按原样运行。一种可能的解决方案是仅返回一个空的React.Fragement元素,但是,这感觉更像是一种肮脏的解决方法。

什么是理想的解决方案?我是否完全走错了道路,是否应该以其他方式管理后台服务的实例化?如果是这样,我如何访问上下文?

2 个答案:

答案 0 :(得分:1)

您需要build a custom hook并在App<app>)组件中调用它。

当前,您有一个使用钩子而不渲染事物的组件:

const MyBackgroundService () => {
  // useHooks

  // No return causes "JSX element type 'void' ..."

  // With return without any functionality is useless.
  // Memory waste, and loses the functionality of custom hooks
  // like returning a value.
  // return <></>
}

答案 1 :(得分:0)

我建议只创建一个自定义钩子,以执行所需的“后台服务”工作:

function useBackgroundService(someStateFromContext) {
  const [backgroundService, setBackgroundService] = useState(null)

  useEffect(() => {
    const bgService = setInterval(() => {
      // check the condition for running the background service
      // for example, to skip the API call, or whatever
      if (someStateFromContext !== 0) {
        return
      }
      callAPI()
        .then(() => {
          console.log(
            `ran bg service with value from context: ${someStateFromContext}`
          )
        })   
    }, 2000)

    setBackgroundService(bgService)

    // make sure you clean up when you no longer need it,
    // for example when component unmounts
    function cleanup() {
      clearInterval(bgService)
    }

    return cleanup;

    // since this `hook` relies on some value from context
    // make sure you include this in your dependency array
    // so that a new background service can be created,
    // and old one be destroyed, when state from context changes
  }, [someStateFromContext])

  // optionally, return `backgroundService`
  return backgroundService;
}

然后,在您的App组件或任何其他组件中,只需使用以下hook

// sample context
const MyContext = React.createContext({
  count: 0
})

function App() {
  const myContext = useContext(MyContext)

  useBackgroundService(myContext.count)

  return (
    <div className="App">
      ...
    </div>
  )
}

以下是示例的链接: