Typescript and Context API, Error: Rendered more hooks than during the previous render
Typescript and Context API, Error: Rendered more hooks than during the previous render
我正在尝试在一个应用程序中同时实现 Typescript 和 Context API。在那种情况下,我正在尝试为登录创建上下文 API。
这是我得到的错误:
Error: Rendered more hooks than during the previous render.
我不确定我做错了什么,这是我的代码:
StateProvider.tsx:
import React, {
Reducer,
Dispatch,
createContext,
useContext,
useReducer,
} from "react";
import { initialState, LoginState } from "./reducer";
export type StateContextType={
state: unknown;
dispatch({}):void;
}
export const StateContext = createContext<StateContextType>({state: {}, dispatch: ()=>{}});
interface IProvider{
reducer:any;
initState:typeof initialState;
children:any;
}
export const StateProvider:React.FC<IProvider> = ({
reducer,
initState,
children,
}) => {
const [state, dispatch] = useReducer(reducer, initState);
const value = { state, dispatch };
return (
<StateContext.Provider value={value}>{children}</StateContext.Provider>
);
};
export const useStateValue = () => useContext(StateContext);
reducer.tsx:
import React, { useState } from "react";
import axios from "./axios";
import { Button, TextField } from "@material-ui/core";
import { Link, useHistory } from "react-router-dom";
import { useStateValue } from './StateProvider'
export const initialState: LoginState = {
user: null,
};
export interface LoginState {
user: string | object | null;
}
type LoginAction = { type: "SET_USER"; payload: string };
function reducer(state: LoginState, action: LoginAction) {
switch (action.type) {
case "SET_USER":
return {
...state,
user: action.payload,
};
default:
return state;
}
}
export default function LoginUseReducer() {
const {state, dispatch} = useStateValue();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const history = useHistory();
const loginHandler = (e: React.FormEvent) => {
e.preventDefault();
const data = {
Email: email,
Password: password,
};
axios
.put("/auth", data)
.then((response) => {
console.log(response);
dispatch({ type: "SET_USER", payload: response });
})
.catch((error) => {
console.log(error.message);
});
};
const handleEmailChange: React.ChangeEventHandler<HTMLInputElement> = (
event
) => {
setEmail(event.target.value);
};
const handlePasswordChange: React.ChangeEventHandler<HTMLInputElement> = (
event
) => {
setPassword(event.target.value);
};
return (
<div>
<TextField
label="Email"
variant="standard"
helperText="Use your student email (JhonDoe@stud.uni-obuda.hu)"
value={email}
onChange={handleEmailChange}
style={{ width: "80%", marginBottom: 30 }}
></TextField>
<TextField
label="Password"
variant="standard"
type="password"
value={password}
onChange={handlePasswordChange}
style={{ width: "80%" }}
></TextField>
<div className="form_buttons" style={{ marginTop: 30 }}>
<Button
onClick={loginHandler}
style={{ fontSize: "large", padding: 15, width: 100 }}
>
Send
</Button>
</div>
</div>
);
}
Login.tsx:
import React from 'react';
import './Login.scss';
import LoginUseReducer, { initialState } from "../../reducer";
function Login() {
return (
<div>
{LoginUseReducer()}
</div>
)
}
export default Login;
如果你们有任何想法,请告诉我。感谢您的宝贵时间!
LoginUseReducer
需要像组件一样渲染而不是像函数一样调用
function Login() {
return (
<div>
<LoginUseReducer />
</div>
)
}
export default Login;
我创建了一个按预期工作的 codesandbox,当 LoginUseReducer
用作组件而不是其他用户指出的功能时。我还做了一些小修改以帮助解决此类问题。
我正在尝试在一个应用程序中同时实现 Typescript 和 Context API。在那种情况下,我正在尝试为登录创建上下文 API。
这是我得到的错误:
Error: Rendered more hooks than during the previous render.
我不确定我做错了什么,这是我的代码:
StateProvider.tsx:
import React, {
Reducer,
Dispatch,
createContext,
useContext,
useReducer,
} from "react";
import { initialState, LoginState } from "./reducer";
export type StateContextType={
state: unknown;
dispatch({}):void;
}
export const StateContext = createContext<StateContextType>({state: {}, dispatch: ()=>{}});
interface IProvider{
reducer:any;
initState:typeof initialState;
children:any;
}
export const StateProvider:React.FC<IProvider> = ({
reducer,
initState,
children,
}) => {
const [state, dispatch] = useReducer(reducer, initState);
const value = { state, dispatch };
return (
<StateContext.Provider value={value}>{children}</StateContext.Provider>
);
};
export const useStateValue = () => useContext(StateContext);
reducer.tsx:
import React, { useState } from "react";
import axios from "./axios";
import { Button, TextField } from "@material-ui/core";
import { Link, useHistory } from "react-router-dom";
import { useStateValue } from './StateProvider'
export const initialState: LoginState = {
user: null,
};
export interface LoginState {
user: string | object | null;
}
type LoginAction = { type: "SET_USER"; payload: string };
function reducer(state: LoginState, action: LoginAction) {
switch (action.type) {
case "SET_USER":
return {
...state,
user: action.payload,
};
default:
return state;
}
}
export default function LoginUseReducer() {
const {state, dispatch} = useStateValue();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const history = useHistory();
const loginHandler = (e: React.FormEvent) => {
e.preventDefault();
const data = {
Email: email,
Password: password,
};
axios
.put("/auth", data)
.then((response) => {
console.log(response);
dispatch({ type: "SET_USER", payload: response });
})
.catch((error) => {
console.log(error.message);
});
};
const handleEmailChange: React.ChangeEventHandler<HTMLInputElement> = (
event
) => {
setEmail(event.target.value);
};
const handlePasswordChange: React.ChangeEventHandler<HTMLInputElement> = (
event
) => {
setPassword(event.target.value);
};
return (
<div>
<TextField
label="Email"
variant="standard"
helperText="Use your student email (JhonDoe@stud.uni-obuda.hu)"
value={email}
onChange={handleEmailChange}
style={{ width: "80%", marginBottom: 30 }}
></TextField>
<TextField
label="Password"
variant="standard"
type="password"
value={password}
onChange={handlePasswordChange}
style={{ width: "80%" }}
></TextField>
<div className="form_buttons" style={{ marginTop: 30 }}>
<Button
onClick={loginHandler}
style={{ fontSize: "large", padding: 15, width: 100 }}
>
Send
</Button>
</div>
</div>
);
}
Login.tsx:
import React from 'react';
import './Login.scss';
import LoginUseReducer, { initialState } from "../../reducer";
function Login() {
return (
<div>
{LoginUseReducer()}
</div>
)
}
export default Login;
如果你们有任何想法,请告诉我。感谢您的宝贵时间!
LoginUseReducer
需要像组件一样渲染而不是像函数一样调用
function Login() {
return (
<div>
<LoginUseReducer />
</div>
)
}
export default Login;
我创建了一个按预期工作的 codesandbox,当 LoginUseReducer
用作组件而不是其他用户指出的功能时。我还做了一些小修改以帮助解决此类问题。