Я пытаюсь реализовать вместе 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.info(response);
dispatch({ type: "SET_USER", payload: response });
})
.catch((error) => {
console.info(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 ([email protected])"
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;
Можете ли вы показать, где и как используется компонент StateProvider?
Конечно index.tsx: `` `` import {StateProvider} from './StateProvider'; импортировать редуктор, {initialState} из './reducer'; ReactDOM.render (<React.StrictMode> <StateProvider initState = {initialState} reducer = {reducer}> <App /> </StateProvider> </React.StrictMode>, document.getElementById ("root")); `` Затем в редукторе то, что вы видите сверху, и все. Надеюсь, это поможет тебе.
Я создал коды, который работает, как ожидалось, когда LoginUseReducer
используется в качестве компонента, а не функции, как указал другой пользователь. Я также внес несколько незначительных изменений, чтобы помочь выявить подобные проблемы.
Спасибо! Ваши решения мне очень помогли: D
У меня та же ошибка :( Теперь компилятор говорит, что проблема внутри const [email, setEmail] = useState ("") в LoginUsereducer; в const [state, dispatch] = useReducer (reducer, initState) в StateProvider; и в диспетчере reducer ({тип: "SET_USER", полезная нагрузка: ответ});