反应:暂停的组件不运行useEffect钩子

时间:2019-02-13 20:08:08

标签: javascript reactjs

目前正在尝试反应钩子和反应悬念。我正在尝试制作一个钩子useApolloQuery,该钩子将获取一些数据并发出承诺,直到数据加载完毕。

我正在使用逻辑来获取useEffect中的数据,但是,如果您立即在组件中抛出诺言(并因此将其挂起),似乎效果永远不会得到发挥。

这是我的代码:(或codeandbox链接:https://codesandbox.io/s/x73pwj164q

function createPromiseResolver() {
  let resolve;
  const promise = new Promise(newResolver => {
    resolve = newResolver;
  });

  return { resolve, promise };
}

function useApolloQuery() {
  const [data, setData] = useState();
  const promsieResolver = createPromiseResolver();

  console.log("this runs");
  useEffect(() => {
    console.log("this doesn't run");

    const timeoutId = setTimeout(() => {
      setData("Some fake data");
      promsieResolver.resolve();
    }, 500);

    return () => clearTimeout(timeoutId);
  });

  if (!data) throw promsieResolver.promise;

  return data;
}

function App() {
  const data = useApolloQuery();

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>{data}</h2>
    </div>
  );
}

因此在该代码中,仅第一个console.log运行,因为useEffect钩子永远不会运行

悬疑应该这样吗?有什么办法可以使它起作用?

2 个答案:

答案 0 :(得分:1)

useEffect无法运行,因为您在实际函数返回之前就抛出了一个诺言,因此该诺言从未得到解决。

问题出在那

if (!data) throw promsieResolver.promise;

未定义初始data,因此!data = true未定义。它抛出了一个承诺,因此该函数从不返回而是短路。删除此行实际上会运行useEffect钩子

解决方案2: 或者,您可以为undefined以外的数据设置初始状态,如下所示 const [data, setData] = useState('initial data');

答案 1 :(得分:0)

刚刚发现了这一点:https://github.com/facebook/react/issues/14563#issuecomment-453184356 因此,除了将所有状态保留在外部存储中之外,似乎没有其他解决办法