i have get token from login with react redux, if i am try to authorized it with this token. the error is show Axios request failed: TypeError: Cannot read property 'token' of undefined i want to authorized it with token. the token is stored in localstorage but it can't authorized it when i am using (Token ${props.token} if i am trying this way (Token 5302f4340a76cd80a855286c6d9e0e48d2f519cb} then my AritcleList.js is Authorized it
here is the react-redux authentication
authAction.js
import axios from 'axios';
import * as actionTypes from './actionTypes';
export const authStart = () => {
return {
type: actionTypes.AUTH_START
}
}
export const authSuccess = token => {
return {
type: actionTypes.AUTH_SUCCESS,
token: token
}
}
export const authFail = error => {
return {
type: actionTypes.AUTH_FAIL,
error: error
}
}
export const logout = () => {
localStorage.removeItem('token');
return {
type: actionTypes.AUTH_LOGOUT
};
}
export const authLogin = (userData) => {
return dispatch => {
dispatch(authStart());
axios.post('http://localhost:8000/rest-auth/login/', userData)
.then(res => {
const token = res.data.key;
localStorage.setItem('token', token);
dispatch(authSuccess(token));
})
.catch(err => {
dispatch(authFail(err))
})
}
}
authReducer.js
import * as actionTypes from '../actions/actionTypes';
import { updateObject } from '../utility';
const initialState = {
isAuthenticated: null,
token: null,
error: null,
loading: false
}
const authStart = (state, action) => {
return updateObject(state, {
isAuthenticated: false,
error: null,
loading: true
});
}
const authSuccess = (state, action) => {
return updateObject(state, {
isAuthenticated: true,
token: action.token,
error: null,
loading: false
});
}
const authFail = (state, action) => {
return updateObject(state, {
error: action.error,
loading: false
});
}
const authLogout = (state, action) => {
return updateObject(state, {
token: null
});
}
export default function (state = initialState, action) {
switch (action.type) {
case actionTypes.AUTH_START: return authStart(state, action);
case actionTypes.AUTH_SUCCESS: return authSuccess(state, action);
case actionTypes.AUTH_FAIL: return authFail(state, action);
case actionTypes.AUTH_LOGOUT: return authLogout(state, action);
default:
return state;
}
}
articleList.js
import React, { useState, useEffect } from 'react';
import { Container, Row, Col } from 'react-bootstrap';
import Card from '../components/Card'
import FullPageLoader from "../components/FullPageLoader";
import axios from 'axios';
import { connect } from 'react-redux'
const NewsList = () => {
const [items, setItems] = useState([])
const [isLoading, setLoading] = useState(true)
const [isAuthenticated, setAuth] = useState(true); //i don't know how to authenticate it when i also login
useEffect((props) => {
const fetchItems = async () => {
try {
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Token ${props.token}`
}
}
const res = await axios.get(`${process.env.REACT_APP_API_URL}/api/`, config);
setItems(res.data)
setLoading(false);
}
catch (err) {
console.log(`😱 Axios request failed: ${err}`);
}
}
fetchItems()
})
}, [items]);
return (
<Container className="mt-5">
< div className="bread-header" >
<h5>Dashboard</h5>
</div >
<hr />
<Row>
<Col sm={8}>
{
isLoading ? <FullPageLoader /> :
<div>
{itemData.map((item, index) => (
<Card key={index} item={item} isAuthenticated={isAuthenticated} ></Card>
))}
</div>
}
</Col>
</Row>
</Container >
)
}
const mapStateToProps = (state) => {
return {
isAuthenticated: state.auth.token,
}
}
export default connect(mapStateToProps)(NewsList)
Look at this thread: Sending the bearer token with axios
You need to add the token to the request as a header.
Related
I have done jwt authorization and registration. But when checking whether the user is authorized, he issues 401 Unauthorized sent a request to receive a refresh token via axios
Here is the authorization verification action:
export const checkAuth = () => {
try {
return async dispatch => {
const response = await axios.get(`http://localhost:5000/api/refresh`, {withCredentials: true})
//console.log(response)
dispatch({
type: SET_USER,
payload: response.data
})
}
} catch (e) {
console.log(e.response?.data?.message);
}
}
here is the reducer:
import {LOGOUT, SET_USER} from "../types";
const initialState = {
currentUser: {},
isAuth: false
}
export const authReducer = (state = initialState, action) => {
switch (action.type) {
case SET_USER:
localStorage.setItem('token', action.payload.accessToken);
return {
...state,
currentUser: action.payload,
isAuth: true
}
case LOGOUT:
localStorage.removeItem('token')
return {
...state,
currentUser: {},
isAuth: false
}
default:
return state
}
}
export const logout = () => ({type: LOGOUT})
Here is the app component:
import './App.css';
import {Route, Routes} from "react-router-dom";
import LoginForm from "./component/LoginForm";
import {useDispatch, useSelector} from "react-redux";
import RegisterForm from "./component/RegisterForm";
import {useEffect} from "react";
import {checkAuth} from "./redux/action";
function App() {
const users = useSelector(state => {
const {authReducer} = state
return authReducer
})
const dispatch = useDispatch()
//console.log(users)
useEffect(() => {
checkAuth() // here I did dispatch()
}, [])
if (!users.isAuth) {
return (<div>
<Routes>
<Route path="/registration" element={<RegisterForm/>}/>
<Route path="/login" element={<LoginForm/>}/>
</Routes>
</div>)
}
console.log(users.currentUser)
return (
<div className="App">
{users.isAuth ? users.currentUser.rows.map(data => <div key={data.id}>{data.email}</div>) : 'log in'}
</div>
);
}
export default App;
Here are the axios settings, but I tried using fetch() and the result is the same (401)
import axios from "axios";
export const API_URL = `http://localhost:5000/api`
const $api = axios.create({
withCredentials: true,
baseURL: API_URL
})
$api.interceptors.request.use((config) => {
config.headers.Authorization = `Bearer ${localStorage.getItem('token')}`
return config;
})
$api.interceptors.response.use((config) => {
return config;
},async (error) => {
const originalRequest = error.config;
if (error.response.status == 401 && error.config && !error.config._isRetry) {
originalRequest._isRetry = true;
try {
const response = await axios.get(`${API_URL}/refresh`, {withCredentials: true})
localStorage.setItem('token', response.data.accessToken);
return $api.request(originalRequest);
} catch (e) {
console.log('NOT AUTHORIZED')
}
}
throw error;
})
export default $api;
I installed cars on the server and call it like this
app.use(cors()) // Use this after the variable declaration / I tried such settings, it didn't help {credentials: true, origin: 'http://localhost:3000'}
For some reason, a 401 error pops up, although everything works in postman!
Why don't I know anymore!???
i am trying to send the error messages that sent from my server ( express ) to axios and the error message displays in toastify component but the error message doesn't show up here is the login axios function with the toastify how can i display toastify message inside my page from redux ?
here is my code :
// redux controller
const login = async (username, password) => {
await axios.post("/login",{username,password,},
{ withCredentials: true });};
// reducer page
export function generateError(prop) {
return function (dispatch) {
dispatch({
type: "USER_FAIL"
});
toast.error(prop);
};
}
export function generateSuccess(prop) {
return function (dispatch) {
dispatch({
type: "USER_SUCCESS"
});
toast.success(prop);
};
}
export const login = createAsyncThunk(
"/login",
async ({ username, password }) => {
try {
const data = await authService.login(username, password);
if (data) {
if (data.errors) {
const { username, password } = data.errors;
if (username) generateError(username)
else if (password) generateError(password);
} else {
generateSuccess(data.success);
}
}
return { user: data };
} catch (error) {
console.log(error);
}
}
);
// login page
const handleSubmit = (e) => {
e.preventDefault();
dispatch(login({ username, password }));
}
i am using react-tostify and #redux-toolkit but the message doesn't display inside my page
i fixed it and here is my code :
// auth.js ( redux page )
export const login = createAsyncThunk(
"/login",
async ({ username, password }) => {
try {
const {data} = await axios.post(
"/login",
{
username,
password,
},
{ withCredentials: true }
);
return { user: data };
} catch (error) {
console.log(error);
}
});
const initialState = user
? { isLoggedIn: true, user }
: { isLoggedIn: false, user: null };
const authSlice = createSlice({
name: "auth",
initialState,
extraReducers: {
[login.fulfilled]: (state, action) => {
state.isLoggedIn = true;
state.user = action.payload.user;
},
[login.rejected]: (state, action) => {
state.isLoggedIn = false;
state.user = null;
},
[logout.fulfilled]: (state, action) => {
state.isLoggedIn = false;
state.user = null;
},
}})
const { reducer } = authSlice; export default reducer;
Login Page :
const { isLoggedIn } = useSelector((state) => state.auth);
const dispatch = useDispatch();
const handleSubmit = (e) => {
e.preventDefault();
dispatch(login({ username, password })).then(data => {
console.log(data)
if (data.payload.user) {
if (data.payload.user.errors) {
const { username, password } = data.payload.user.errors;
if (username) generateError(username)
else if (password) generateError(password);
} else {
generateSuccess(data.success);
navigate("/dashboard");
}
}
})
}
i realized when i back the data it has an object name payload i used it to get the error messages from express and then i put the message in toastify function gettingError and here it is
const generateError = error => {
toast.error(error, {
position: "bottom-right",
})
}
Hai I'm also looking for the same problem while searching I found a solution at with this : react-toastify-with-redux
my Code : authAction.js
import 'react-toastify/dist/ReactToastify.min.css';
import { toast} from 'react-toastify';
export const registerUser = (userData) => dispatch =>{
axios.post('user/register',userData)
.then(res=>toast.success('Your Account Created Successfully 👍'))
.then(res=> window.location = '/authentication/sign-in')
.catch(err=>dispatch(
{
type: GET_ERRORS,
payload: err.response.data
}
),toast.error("Error 😣"))
// .catch((err)=> {return })
};
On your signUp page just add
<ToastContainer />
That's all ...
This answer is probably late. But I came across this problem and decided to do it my way. I know there is toast. promise to handle promises and I don't want to call dispatch.then every time. So I can up with passing dispatch to my action wrapper. Here is my code.
// utils.ts
type ArgumentTypes<F extends CallableFunction> = F extends (
...args: infer A
) => any
? A[0]
: never;
export const withToast = <T = AnyAction | typeof createAsyncThunk>(
action: T,
{ pending, error, success }: ToastPromiseParams<T>
) => {
return (
dispatch: ReturnType<typeof useAppDispatch>,
actionParams?: ArgumentTypes<T & CallableFunction> | void
) => {
const promise = dispatch(
(action as CallableFunction)(actionParams as any)
).unwrap();
toast.promise(promise, {
pending,
error,
success,
});
};
};
// actions.ts
export const login = createAsyncThunk(
"user/login",
async (payload: {
email: string;
password: string;
}): Promise<Partial<LoginAPIResponse>> => {
const { data } = await axios.post(`${API}/${LOGIN_EP}/`, payload);
return data;
}
);
export const loginWithToast = withToast(login, {
pending: "Logging in...",
error: {
render: (error: any) => {
return error?.password || error?.email
? "Invalid email or password"
: "Something went wrong";
},
},
success: "Logged in successfully",
});
// usage in component
const dispatch = useAppDispatch();
loginWithToast(dispatch, {
email: values.email.value,
password: values.password.value,
});
First createAsyncThunk:
import { coreAxios } from "utilities/axios"; // Own customized axios
import { createAsyncThunk } from "#reduxjs/toolkit";
const BASE_URL = process.env.REACT_APP_MAIN_URL
export const GetProducts = createAsyncThunk(
"inventory/GetProducts",
async () => {
const {data} = await coreAxios.get(`${BASE_URL}/api/product/list/`);
return data
}
);
Second createSlice:
import { createSlice } from "#reduxjs/toolkit";
import { GetProducts } from "services/inventory/product.service";
import { toast } from 'react-toastify';
export const productSlice = createSlice({
name: "products",
initialState: {
productsList: [],
productsLoading: false,
productsError: null,
},
extraReducers:
(builder) => {
builder.addCase(GetProducts.pending, (state) => {
toast.loading('Promise is pending...')
state.productsLoading = true
});
builder.addCase(GetProducts.fulfilled, (state, action) => {
toast.dismiss();
toast.success('Promise resolved 👌');
state.productsList = action.payload
state.productsLoading = false
state.productsError = null
});
builder.addCase(GetProducts.rejected, (state, action) => {
toast.dismiss();
toast.error('Promise rejected 🤯 😣')
state.productsLoading = false
state.productsError = action.error?.message
});
},
});
export default productSlice.reducer;
Third page:
import { ToastContainer } from 'react-toastify';
import { useSelector, useDispatch } from "react-redux";
import { GetProducts } from 'services/inventory/product.service';
const Product = () => {
const { productsList, productsLoading, productsError } = useSelector((state) => state.products);
const dispatch = useDispatch();
useEffect(() => {
dispatch(GetProducts());
}, []);
return (
<div className="grid crud-demo">
<h1>Hello Alim</h1>
<ToastContainer />
</div>
);
}
So I have a mobile app in react native for which I am trying to create the auth flow properly.I had this first as a web app and then now trying to do the same as a mobile app. I am using redux for state management.
Here is the flow: Once the user logs in or registers, I send the data to the backend using axios. The backend generates a user token. I would like to create a system where I can fetch the token when a user logs in and store that with AsyncStorage so that I can directly log the user in when he or she tries to open the app again.
Here is the code, more than happy to answer any questions, this was done through a react tutorial really:
LoginScreen.js
const Login = ( { navigation }) => {
const [email, setEmail] = useState();
const [password, setPassword] = useState();
const [message, setMessage] = useState(null)
// Errors
const [EmailMessage, setEmailMessage] = useState(null);
const [PasswordMessage, setPasswordMessage] = useState(null);
const dispatch = useDispatch();
const userLogin = useSelector((state) => state.userLogin);
const { loading, error, userInfo } = userLogin
useEffect(() => {
if (userInfo) {
navigation.navigate('MainTabs', { screen: 'Home'});
}
}, [navigation, userInfo]);
const submitHandler = (e) => {
e.preventDefault();
if (!email) {
alert('Please fill in the email');
return
};
if (!password) {
alert('Please fill in the password');
return
}
dispatch(login(email, password));
};
The return part is the frontend code so left that out for the sake of brevity
Now the redux part:
userActions.js
import axios from "axios";
import { USER_LOGIN_FAIL, USER_LOGIN_REQUEST, USER_LOGIN_SUCCESS, USER_LOGOUT, USER_REGISTER_FAIL, USER_REGISTER_SUCCESS, USER_REGISTER_REQUEST } from "../constants/userConstants"
import AsyncStorage from '#react-native-async-storage/async-storage';
export const login = (email, password) => async(dispatch) => {
try {
dispatch({ type: USER_LOGIN_REQUEST });
const config = {
headers: {
"Content-type": "application/json"
}
}
const {data} = await axios.post("api/url", {email, password}, config)
dispatch({type: USER_LOGIN_SUCCESS, payload:data});
await AsyncStorage.setItem("userInfo", JSON.stringify(data))
} catch (error) {
dispatch({
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
})
console.log("This login attempt is unsuccessful");
}
}
export const logout = () => async (dispatch) => {
await AsyncStorage.removeItem("userInfo")
dispatch({ type: USER_LOGOUT });
};
export const register = (full_name, email, password, social) => async(dispatch) => {
try {
dispatch({type: USER_REGISTER_REQUEST});
const config = {
headers: {
"Content-type": "application/json"
}
};
const {data} = await axios.post("api/url", {full_name, email, password, social}, config);
dispatch({ type: USER_REGISTER_SUCCESS, payload: data});
dispatch({ type: USER_LOGIN_SUCCESS, payload: data});
await AsyncStorage.setItem("userInfo", JSON.stringify(data))
} catch (error) {
dispatch({type: USER_REGISTER_FAIL, payload:
error.response && error.response.data.message
? error.response.data.message
: error.message
})
}}
userReducers.js
import { USER_LOGIN_REQUEST, USER_REGISTER_FAIL, USER_REGISTER_REQUEST, USER_REGISTER_SUCCESS } from "../constants/userConstants";
import { USER_LOGIN_SUCCESS, USER_LOGIN_FAIL, USER_LOGOUT } from "../constants/userConstants";
export const userLoginReducer = (state = {}, action) => {
switch (action.type) {
case USER_LOGIN_REQUEST:
return {loading: true}
case USER_LOGIN_SUCCESS:
return {loading: false, userInfo: action.payload}
case USER_LOGIN_FAIL:
return {loading: false, error:action.payload}
case USER_LOGOUT:
return {}
default:
return state;
}
}
export const userRegisterReducer = (state = {}, action) => {
switch (action.type) {
case USER_REGISTER_REQUEST:
return {loading:true}
case USER_REGISTER_SUCCESS:
return {loading:false, userInfo: action.payload}
case USER_REGISTER_FAIL:
return {loading:false, error: action.payload}
default:
return state;
}
}
store.js
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from "redux-thunk";
import { userLoginReducer, userRegisterReducer } from './src/redux/reducers/userReducers';
import AsyncStorage from '#react-native-async-storage/async-storage';
const reducer = combineReducers({
//contains reducers
userLogin: userLoginReducer,
userRegister: userRegisterReducer
});
const middleware = [thunk];
const getData = async () => {
try {
const value = await AsyncStorage.getItem("userInfo")
return value != null ? JSON.parse(value) : null;
} catch(e) {
console.log("this attempt is not successful");
}
}
const userInfoFromStorage = getData() || null;
alert(JSON.stringify(userInfoFromStorage))
const initialState = {
userLogin: {userInfo: userInfoFromStorage}
};
const store = createStore(
reducer,
initialState,
applyMiddleware(...middleware)
);
export default store
I would appreciate any help here as I am not able to resolve how to solve this is this is a promise issue on fetch or something more general than that. I have a token generated in the backend once I register a user. I would really appreciate if anyone knows of the best way on how to fetch and save that token and log the user in if the user had already logged in
First, create a file with the name authProvider.ts. This will hold objects, with key as isAuthenticated and async getAuthToken() with callback function as property.
const authProvider: any = {
isAuthenticated: false,
authToken: null,
async getAuthToken(callback: VoidFunction) {
await GetSessionData('Access-token').then(
res => {
if (res) {
authProvider.isAuthenticated = true;
authProvider.authToken = res;
callback();
} else {
authProvider.isAuthenticated = false;
authProvider.authToken = res;
callback();
}
}
);
}
};
export { authProvider };
export const GetSessionData = async (key: string) => {
return await AsyncStorage.getItem(
key,
(err, value) => {
if (err) {
console.log(err);
} else {
return value;
}
}
);
}
In app.tsx
In App component we will call the above authProvider to get the token from Async storage using await. Once done it will execute the below callback function logic.
const App = () => {
const [isLoading, setLoading] = useState<boolean>(true);
useEffect(() => {
authProvider.getAuthToken(() => {
if (authProvider.isAuthenticated) {
store.dispatch(isAuthenticatedUser(true));
setLoading(false);
} else {
store.dispatch(isAuthenticatedUser(false));
setLoading(false);
// *** redirect to login page logic ***.
}
});
}, []);
return (
<>
<Provider store={store}>
{
!isLoading ?
<Dashboard /> :
<AppLoader />
}
</Provider>
</>
);
}
I have wriiten the below code in which the city the alert function initially works fine when a wrong city name or no city name is entered. But after the Weather details are displayed here again when I click on submit then it re renders the previous state and new one and gives both result.
Code:
import React, { FC, useState, FormEvent } from "react";
import { useDispatch } from "react-redux";
import { Header, Input, Button } from "../style";
import {
getWeather,
setLoading
} from "../../store/actions/WeatherAction/weatherActions";
import { setAlert } from "../../store/actions/AlertAction/alertActions";
interface SearchProps {
title: string;
}
const Search: FC<SearchProps> = ({ title }) => {
const dispatch = useDispatch();
const [city, setCity] = useState("");
const changeHandler = (e: FormEvent<HTMLInputElement>) => {
setCity(e.currentTarget.value);
};
const submitHandler = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
dispatch(setLoading());
dispatch(getWeather(city));
setCity("");
};
return (
<>
<Header>
{title}
<form onSubmit={submitHandler}>
<Input
type="text"
placeholder="Enter city name"
value={city}
onChange={changeHandler}
/>
<br />
<Button>Search</Button>
</form>
</Header>
</>
);
};
export default Search;
weatherAction.ts
import { ThunkAction } from "redux-thunk";
import { RootState } from "../..";
import {
WeatherAction,
WeatherData,
WeatherError,
GET_WEATHER,
SET_LOADING,
SET_ERROR
} from "../../types";
export const getWeather = (
city: string
): ThunkAction<void, RootState, null, WeatherAction> => {
return async (dispatch) => {
try {
const res = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=3020950b62d2fb178d82816bad24dc76`
);
if (!res.ok) {
const resData: WeatherError = await res.json();
throw new Error(resData.message);
}
const resData: WeatherData = await res.json();
dispatch({
type: GET_WEATHER,
payload: resData
});
} catch (err) {
dispatch({
type: SET_ERROR,
payload: err.message
});
}
};
};
export const setLoading = (): WeatherAction => {
return {
type: SET_LOADING
};
};
export const setError = (): WeatherAction => {
return {
type: SET_ERROR,
payload: ""
};
};
weatherReducer
import {
WeatherState,
WeatherAction,
GET_WEATHER,
SET_LOADING,
SET_ERROR
} from "../../types";
const initialState: WeatherState = {
data: null,
loading: false,
error: ""
};
export default (state = initialState, action: WeatherAction): WeatherState => {
switch (action.type) {
case GET_WEATHER:
return {
data: action.payload,
loading: false,
error: ""
};
case SET_LOADING:
return {
...state,
loading: true
};
case SET_ERROR:
return {
...state,
error: action.payload,
loading: false
};
default:
return state;
}
};
The problem is that your reducer does not clear the weather data when processing a SET_ERROR action. If you want to clear the weather data when you receive an error, you should set data back to null like this:
case SET_ERROR:
return {
data: null,
error: action.payload,
loading: false
};
isAuthenticated is undefined when i run this code. how can is use isAuthenticated with mapStateProps. if i am use Token `(Token '5302f4340a76cd80a855286c6d9e0e48d2f519cb'} like this then it's working fine but i want Authorized it with props.isAuthenticated anybody know how can i solve this issue?
authAction.js
import axios from 'axios';
import * as actionTypes from './actionTypes';
export const authStart = () => {
return {
type: actionTypes.AUTH_START
}
}
export const authSuccess = token => {
return {
type: actionTypes.AUTH_SUCCESS,
token: token
}
}
export const authFail = error => {
return {
type: actionTypes.AUTH_FAIL,
error: error
}
}
export const logout = () => {
localStorage.removeItem('token');
return {
type: actionTypes.AUTH_LOGOUT
};
}
export const authLogin = (userData) => {
return dispatch => {
dispatch(authStart());
axios.post('http://localhost:8000/rest-auth/login/', userData)
.then(res => {
const token = res.data.key;
localStorage.setItem('token', token);
dispatch(authSuccess(token));
})
.catch(err => {
dispatch(authFail(err))
})
}
}
authReducer.js
import * as actionTypes from '../actions/actionTypes';
import { updateObject } from '../utility';
const initialState = {
isAuthenticated: null,
token: null,
error: null,
loading: false
}
const authStart = (state, action) => {
return updateObject(state, {
isAuthenticated: false,
error: null,
loading: true
});
}
const authSuccess = (state, action) => {
return updateObject(state, {
isAuthenticated: true,
token: action.token,
error: null,
loading: false
});
}
const authFail = (state, action) => {
return updateObject(state, {
error: action.error,
loading: false
});
}
const authLogout = (state, action) => {
return updateObject(state, {
token: null
});
}
export default function (state = initialState, action) {
switch (action.type) {
case actionTypes.AUTH_START: return authStart(state, action);
case actionTypes.AUTH_SUCCESS: return authSuccess(state, action);
case actionTypes.AUTH_FAIL: return authFail(state, action);
case actionTypes.AUTH_LOGOUT: return authLogout(state, action);
default:
return state;
}
}
index.js
import { combineReducers } from 'redux';
import auth from './authReducer'
export default combineReducers({
auth: auth
});
articleList.js
const NewsList = (props) => {
// ...
const fetchItems = async () => {
try {
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Token ${props.isAuthenticated}`
}
}
const res = await axios.get(`${process.env.REACT_APP_API_URL}/api/`, config);
setItems(res.data)
setLoading(false);
}
catch (err) {
console.log(`😱 Axios request failed: ${err}`);
}
}
fetchItems()
})
}, [items]);
// ...
}
const mapStateToProps = (state) => {
return {
isAuthenticated: state.auth.token
}
}
export default connect(mapStateToProps)(NewsList)
You need to debug your code. Start by connecting the dots: The output tells you that props.isAuthenticated is undefined. You pass this in from state.auth.token in mapStateToProps():
const mapStateToProps = (state) => {
return {
isAuthenticated: state.auth.token
}
}
So state.auth.token must be undefined also. That's as far as I can get from what you have shown me. You will need to debug further to figure out why. You can use the React Dev Tools to inspect props of your components. You can use Redux Dev Tools to inspect and manipulate the redux state. Check what the value of auth.token is in state. Look where it is supposed to be set and find out why it isn't getting set to a valid value.
Be sure to check this article for tips on how to debug your code.