Jestem nowa w reduxie, dostaję błąd:
TypeError: login is not a function at onSubmit.
Login.js:
import { Box, Button, Paper, TextField, Typography } from "@mui/material";
import React, { useEffect, useRef, useState, useContext } from "react";
import AuthContext from "../context/authProvider";
import { Link, redirect } from "react-router-dom";
import { connect } from "react-redux";
import { login } from "../actions/auth";
export const Login = ({login}) => {
const [formData, setFormData] = useState({
email: "",
password: "",
});
const { email, password } = formData;
const onChange = (e) =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = e => {
e.preventDefault();
login(email, password);
};
return (
<>
{success ? (
<Typography>OK </Typography>
) : (
<Box
width="100%"
height="90vh"
display="flex"
justifyContent="center"
alignItems="center"
>
<Paper sx={{ height: "40vh", width: 280, padding: "1rem" }}>
<Typography
ref={errRef}
className={errMsg ? "errMsg" : "offscreen"}
aria-live="assertive"
>
{errMsg}
</Typography>
<Typography variant="h4">Login</Typography>
<Box display="flex" flexDirection="column" padding="1rem">
<form onSubmit={(e) => onSubmit(e)}>
<TextField
size="small"
placeholder="Username"
sx={{ marginBottom: "1rem" }}
onChange={(e) => onChange(e)}
ref={userRef}
value={email}
name="email"
id="username"
required
></TextField>
<TextField
type="password"
size="small"
name="password"
placeholder="Password"
sx={{ marginBottom: "2rem" }}
onChange={(e) => onChange(e)}
value={password}
id="password"
required
></TextField>
<Button size="large" variant="contained" type="submit">
Login
</Button>
</form>
<Typography variant="caption" sx={{ marginTop: "1.5rem" }}>
Dont have account yet?{" "}
<Link
to="/register"
style={{ textDecoration: "none", color: "inherit" }}
>
Click here
</Link>
</Typography>
<Typography variant="caption" sx={{ marginTop: "0.5rem" }}>
Forgot password? {" "}
<Link
to="/resetPassword"
style={{ textDecoration: "none", color: "inherit" }}
>
Reset Password
</Link>
</Typography>
</Box>
</Paper>
</Box>
)}
</>
);
};
export default connect(null,{login} )(Login)
auth.js:
import { LOGIN_SUCCESS, LOGIN_FAIL, LOAD_USER_SUCCESS, LOAD_USER_FAIL} from './types';
import api from '../api/posts';
export const load_user = () => async dispatch => {
if(localStorage.getItem('access')){
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `JWT ${localStorage.getItem('access')}`,
'Accept': 'application/json'
}
};
try{
const response = await api.get('auth/v1/users/me/', config);
dispatch({
type: LOAD_USER_SUCCESS,
payload: response.data
})
}catch(err){
dispatch({
type: LOAD_USER_FAIL,
})
}
} else{
dispatch({
type: LOAD_USER_FAIL,
})
}
}
export const login = (email, password) => async (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/json'
}
};
const body = JSON.stringify({email, password});
try{
const response = await api.post('auth/v1/jwt/create/', body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: response.data
});
dispatch(load_user());
}catch(err){
dispatch({
type: LOGIN_FAIL,
})
}
};
App.js:
import { Box } from "@mui/material";
import "./App.css";
import NavBar from "./components/navbar";
import { Route, Routes } from "react-router-dom";
import { HomePage } from "./homepage/homePage";
import { Login } from "./login/Login";
import { Register } from "./register/Register";
import { AccountSettings } from "./accountSettings/AccountSettings";
import { JobOffers } from "./jobOffers/JobOffers";
import { UserJobOffer } from "./userJobOffer/UserJobOffer";
import { AddJobOffer } from "./addJobOffer/AddJobOffer";
import { JobOfferDetails } from "./jobOfferDetails/JobOfferDetails";
import { EditOffer } from "./editOffer/EditOffer";
import { Provider } from "react-redux";
import store from "./store";
import Layout from "./hocs/Layout";
function App() {
return (
<>
<Provider store={store}>
<Layout>
<Routes>
<Route exact path="/" element={<HomePage />} />
<Route exact path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/settings" element={<AccountSettings />} />
<Route path="/allOffers" element={<JobOffers />} />
<Route path="/userOffers" element={<UserJobOffer />} />
<Route path="/addJobOffer" element={<AddJobOffer />} />
<Route path="/offerDetails/:id" element={<JobOfferDetails />} />
<Route path="/addOffer" element={<AddJobOffer />} />
<Route path="/editOffer" element={<EditOffer />} />
</Routes>
</Layout>
</Provider>
</>
);
}
export default App;
store.js:
import { createStore, applyMiddleware } from "redux";
import { configureStore } from '@reduxjs/toolkit'
import {composeWithDevTools} from 'redux-devtools-extension';
import thunk from 'redux-thunk'
import rootReducer from './reducers';
const initialState = {};
const middleware = [thunk];
const store = configureStore(
{reducer: rootReducer},
initialState,
composeWithDevTools(applyMiddleware(...middleware))
)
export default store;
Chciałam nauczyć się reduxa z tego filmiku, sprawdzając kod, mam prawie identyczny:
https://www.youtube.com/watch?v=5gnixz0Q3co&list=PLJRGQoqpRwdfoa9591BcUS6NmMpZcvFsM&index=7&ab_channel=BryanBrkic
Czy błąd może być powodowany inną wersją reduxa? CreateStore z tego co widziałam, zmienił się na ConfigureStore.