由于useEffect挂钩在16.9中正常工作而导致应用冻结

代码在React 16.8上运行良好,但在> = 16.9时冻结。我查看了16.9的更改,但是当发生无限循环而不是行为的实际更改时,它提到的只是一个额外的警告,所以这不应该发生,而是这样。

将useEffect的依赖项设置为[]确实会破坏循环,但意味着代码需要修改,我不确定如何修改。

以下代码也可以在沙箱here中找到。该版本设置为16.8.4,因此不会冻结。

index.jsx

//...
import { SessionContext,getSessionCookie,setSessionCookie } from "./session";
import "./styles.css";

const history = createBrowserHistory();

const LoginHandler = ({ history }) => {
  const [email,setEmail] = useState("");
  const [loading,setLoading] = useState(false);
  const handleSubmit = async e => {
    e.preventDefault();
    setLoading(true);
    // NOTE request to api login here instead of this fake promise
    await new Promise(r => setTimeout(r(),1000));
    setSessionCookie({ email });
    history.push("/");
    setLoading(false);
  };

  if (loading) {
    return <h4>Logging in...</h4>;
  }

  return (
    //...
  );
};

const LogoutHandler = ({ history }: any) => {
  //...
};

const ProtectedHandler = ({ history }) => {
   //...
};

const Routes = () => {
  const [session,setSession] = useState(getSessionCookie());
  useEffect(
    () => {
      setSession(getSessionCookie());
    },[session]
  );

  return (
    <SessionContext.Provider value={session}>
      <Router history={history}>
        <div classname="navbar">
          <h6 style={{ display: "inline" }}>Nav Bar</h6>
          <h6 style={{ display: "inline",marginLeft: "5rem" }}>
            {session.email || "No user is logged in"}
          </h6>
        </div>
        <Switch>
          <Route path="/login" component={LoginHandler} />
          <Route path="/logout" component={LogoutHandler} />
          <Route path="*" component={ProtectedHandler} />
        </Switch>
      </Router>
    </SessionContext.Provider>
  );
};

const App = () => (
  <div classname="App">
    <Routes />
  </div>
);

const rootElement = document.getElementById("root");
render(<App />,rootElement);

session.ts

import React from "react";
import * as Cookies from "js-cookie";

export const setSessionCookie = (session: any): void => {
  Cookies.remove("session");
  Cookies.set("session",session,{ expires: 14 });
};

export const getSessionCookie: any = () => {
  const sessionCookie = Cookies.get("session");

  if (sessionCookie === undefined) {
    return {};
  } else {
    return JSON.parse(sessionCookie);
  }
};

export const SessionContext = React.createContext(getSessionCookie());

预期结果:应用程序在16.9中起作用,就像在16.8中一样

实际结果:由于在useEffect中存在无限循环,应用程序冻结在16.9中

错误消息:警告:超出最大更新深度。当组件在useEffect中调用setState时会发生这种情况,但useEffect要么没有依赖项数组,要么在每个渲染器上都有一个依赖项更改。

JACYH 回答:由于useEffect挂钩在16.9中正常工作而导致应用冻结

JSON.parse(sessionCookie)总是返回一个新对象。

setSession(getSessionCookie())将会话设置为该新对象

[session]表示只要在状态中设置了新的会话对象(每次渲染都会发生)就运行。

这就是您所看到的无限循环。要停止它,您可以执行以下操作:

useEffect(
    () => {
      const newSessionCookie = getSessionCookie()
      if(newSessionCookie.uniqueId !== session.uniqueId) {
        setSession(getSessionCookie());
      }
    },[session]
  )

您只需要确保您具有cookie的某些唯一标识符即可。

本文链接:https://www.f2er.com/3122927.html

大家都在问