Код отлично работает на React 16.8, но зависает на> = 16.9. Я посмотрел на изменения для 16.9, но все, что было упомянуто, было дополнительным предупреждением о бесконечном цикле, а не фактическим изменением поведения, так что этого не должно происходить, но оно есть.
Установка зависимости useEffect на [] действительно прерывает цикл, но означает, что код необходимо изменить, и я не уверен, как это сделать.
Приведенный ниже код также можно найти в изолированной программной среде здесь. Версия установлена на 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
Фактический результат: приложение зависает в версии 16.9 из-за предполагаемого бесконечного цикла использования.
Сообщение об ошибке: Предупреждение: превышена максимальная глубина обновления. Это может произойти, когда компонент вызывает setState внутри useEffect, но useEffect либо не имеет массива зависимостей, либо одна из зависимостей изменяется при каждом рендеринге.