让 useEffect 钩子在组件渲染之前运行

4

我有一个useEffect钩子,我在我的App.js文件中使用它。它将数据放入redux store中,我需要在我的应用程序中使用这些数据。但是它在useEffect运行之前就开始渲染了,因此数据是未定义的。然后useEffect正确运行。 我需要在任何东西被渲染之前运行useEffect。我该怎么做?或者我应该使用什么其他解决方案?我已经尝试完全删除useEffect并只运行操作,但结果是它无休止地运行。 这是我的代码:

function App() {
  const app = useSelector(state => state.app);
  const auth = useSelector(state => state.auth);
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(authActions.checkUser());
  }, [dispatch]);

  console.log(auth.user); //undefined

  return (
    <ThemeProvider theme={!app.theme ? darkTheme : theme}>
      <CssBaseline />
      <React.Fragment>
        {/* TODO: Display drawer only when logged in */}
        {/* <Drawer></Drawer> */}
        <Switch>
          <Route exact path="/" component={Login} />
          <Route exact path="/dashboard">
            <Dashboard user={auth.user} /> //auth.user is undefined when this gets rendered
          </Route>
          <Route exact path="/register" component={Register} />
        </Switch>
      </React.Fragment>
    </ThemeProvider>
  );
}

export const checkUser = () => async dispatch => {
  let token = localStorage.getItem("auth-token");
  if (token === null) {
    localStorage.setItem("auth-token", "");
    token = "";
  }
  const tokenRes = await Axios.post("http://localhost:5000/users/tokenIsValid", null, {
    headers: { "x-auth-token": token }
  });
  if (tokenRes.data) {
    const userRes = await Axios.get("http://localhost:5000/users/", {
      headers: { "x-auth-token": token }
    });
    dispatch({
      type: CHECK_USER,
      token,
      user: userRes.data
    });
  }
};

2个回答

5
我需要让 useEffect 在任何东西被渲染之前运行,我该如何做到呢?
你无法使 useEffect 在初始渲染之前运行。
就像 class 组件中的 componentDidMount 在初始渲染之后运行一样,useEffect 也是在初始渲染后运行,然后它的执行取决于是否向 useEffect 钩子传递了第二个参数即依赖项数组。
还有其他解决方法吗?
您可以通过确保在异步获取数据可用后才呈现它来有条件地渲染内容。
return (
   { auth ? <render content> : null}
);

或者
return (
   { auth && <render content> }
);

提示:角括号< 或 >不属于语法的一部分。它们只是用作需要呈现的内容的占位符。

详细信息请参见:React - 条件渲染


谢谢,这个方法有效,但显然,在渲染内容显示之前会有轻微的延迟。我该如何避免这种延迟? - Filip
当数据正在加载时,您可以渲染某种加载旋转器以指示数据正在加载。 - Yousaf

1

替代方案

您可以使用useMemo,它不会等待重新渲染。它也会根据依赖项执行相同的方式,就像useEffect一样。

useMemo(()=>{
    doSomething() //Doesn't want until render is completed 
}, [dep1, dep2])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接