redux-toolkit typo error action is not a function - javascript

I've looked on other posts and it seemed to be a naming export thing, but I looked over and over my code and can't figure it out. I will appreciate any advice.
this is the error I'm getting:
TypeError: (0 , _redux_wetherSlice__WEBPACK_IMPORTED_MODULE_2__.setLocalLatitude) is not a function
at localWether.js:14
slice component
import { createSlice } from "#reduxjs/toolkit";
export const wetherSlice = createSlice({
name: "wether",
initialState: {
localLocation: {
latitude: "",
longitude: "",
},
reducers: {
setLocalLatitude: (state, action) => {
state.localLocation.latitude = action.payload;
},
setLocalLongitude: (state, action) => {
state.localLocation.longitude = action.payload;
},
},
},
});
export const { setLocalLongitude, setLocalLatitude } = wetherSlice.actions;
export default wetherSlice.reducer;
react component
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { setLocalLatitude, setLocalLongitude } from "../../redux/wetherSlice";
const LocalWether = () => {
const dispatch = useDispatch();
const { localLocation } = useSelector((state) => state.wether);
useEffect(() => {
navigator.geolocation.getCurrentPosition((position) => {
try {
console.log(position);
dispatch(setLocalLatitude(position.coords.latitude));
dispatch(setLocalLongitude(position.coords.longitude));
} catch (err) {
console.log(err);
}
});
}, []);
console.log(localLocation);
return <button>Click For Location</button>;
};
export default LocalWether;
store
import { configureStore } from "#reduxjs/toolkit";
import wetherReducer from "../redux/wetherSlice";
const store = configureStore({
reducer: { wether: wetherReducer },
});
export default store;

Related

why is state not being updated?

Slice
import { createSlice } from '#reduxjs/toolkit';
const initialState: { value: number } = { value: 0 };
export const testSlice = createSlice({
name: 'test',
initialState,
reducers: {
test: (state) => {
state.value += 1;
},
},
});
export const { test } = testSlice.actions;
Combine
import { combineReducers } from '#reduxjs/toolkit';
import { authSlice } from './auth';
import { productsSlice } from './products';
import { testSlice } from './test';
import { userSlice } from './user';
export const rootReducer = combineReducers({
user: userSlice.reducer,
auth: authSlice.reducer,
products: productsSlice.reducer,
test: testSlice.reducer,
});
export type RootState = ReturnType<typeof rootReducer>;
Store
import { configureStore } from '#reduxjs/toolkit';
import storage from 'utils/storage';
import { rootReducer } from './rootReducer';
declare global {
interface Window {
store: any;
}
}
const reHydrateStore = () => {
if (storage.getToken() !== null) {
return storage.getToken();
}
return false;
};
// !TODO add types
// #ts-ignore
const localStorageMiddleware = (store) => (next) => (action) => {
if (action.type.match('auth')) {
const result = next(action);
storage.setToken(store.getState().auth.token);
return result;
}
return next(action);
};
export const store = configureStore({
reducer: rootReducer,
preloadedState: {
auth: {
token: reHydrateStore() || '',
loading: false,
},
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(localStorageMiddleware),
});
window.store = store.getState();
When I output store.test to the console, the value remains old, but auth reducer works correctly.
Also I see that the state after the update in the reducers is 0.
Why is state not being updated?
Above are examples of my code:
Сreate Slice
Combine reducers
Store settings (and output store in console)

useSelector Returning Undefined object

I am trying to store users fetched by random users api and trying to dispatch it to my store i have store users with an empty array, when i am trying to get users using useSelector i am getting an undefined object.
Here is my store.js:
import { configureStore } from "#reduxjs/toolkit";
import counterReducer from "../features/counter/counterSlice";
import userReducer from "../features/users/userSlice";
export const store = configureStore({
reducer: {
counter: counterReducer,
user: userReducer,
},
});
Here is userSlice.js
import { createSlice } from "#reduxjs/toolkit";
export const userSlice = createSlice({
name: "users",
initialState: {
userArray: [],
},
reducers: {
getUsers: (state, action) => {
state.userArray = action.payload;
}
}
})
export const { getUsers } = userSlice.actions;
export const selectUsers = (state) => state.users.userArray;
export default userSlice.reducer;
Here is App.js
import logo from './logo.svg';
import './App.css';
import {useSelector, useDispatch } from 'react-redux';
import { getUsers, selectUsers } from './features/users/userSlice';
function App() {
const dispatch = useDispatch();
const users = useSelector(selectUsers);
const fetchUsers = async () => {
fetch("https://gorest.co.in/public/v2/users")
.then((response) => response.json())
.then((data) => {
console.log("data=====", data);
dispatch(getUsers(data));
});
};
return (
<div className="App">
<header className="App-header">
<button onClick={fetchUsers}>Get Users</button>
{users.length > 0 &&
users.map((user) => {
<li>user.name</li>;
})}
</header>
</div>
);
}
export default App;
you are mixing up state.user and state.users
either rename user in configureStore to users or use state.user.userArray

React Redux, trying to add products to cart

I am trying to add products to shopping cart by storing them in local storage but, they are not getting stored. I looked into Redux-dev-tools and found out my state is not updating:
As you can see action is getting fired but my state is not updating:
Here is the source code:
cartAction.js
import axios from "axios"; import { CART_ADD_ITEM, CART_REMOVE_ITEM } from "../constants/cartConstants";
export const addToCart = (id, qty) => async (dispatch, getState) => { const { data } = await axios.get(`/api/product/${id}`);
dispatch({
type: CART_ADD_ITEM,
payload: {
productID: data.product._id,
name: data.product.name,
image: data.product.image,
price: data.product.price,
countInStock: data.product.countInStock,
qty,
}, });
localStorage.setItem("cartItems", JSON.stringify(getState().cart.cartItems)); };
cartReducer.js
import { CART_ADD_ITEM, CART_REMOVE_ITEM } from "../constants/cartConstants";
export const cartReducer = (state = { cartItems: [] }, action) => {
switch (action.state) {
case CART_ADD_ITEM:
const item = action.payload;
const existItem = state.cartItems.find(
(x) => x.productID === item.productID
);
if (existItem) {
return {
...state,
cartItems: state.cartItems.map((x) =>
x.productID === existItem.productID ? item : x
),
};
} else {
return {
...state,
cartItems: [...state.cartItems, item],
};
}
// case CART_REMOVE_ITEM:
// return {};
default:
return state;
}
};
store.js
import { createStore, combineReducers, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
// reducers
import {
productDetailsReducer,
productListReducer,
} from "./reducers/productReducers";
import { cartReducer } from "./reducers/cartReducers";
const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
});
const cartItemsFromStorage = localStorage.getItem("cartItems")
? JSON.parse(localStorage.getItem("cartItems"))
: [];
const initialState = {
cart: { cartItems: cartItemsFromStorage },
};
const middleware = [thunk];
const store = createStore(
reducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
CartScreen.js
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { addToCart, removeFromCart } from "../../redux/actions/cartActions";
import { Link } from "react-router-dom";
import ErrorMessage from "../../components/ErrorMessage/ErrorMessage";
import "./CartScreen.scss";
const CartScreen = ({ match, location, history }) => {
const productID = match.params.id;
const qty = location.search ? Number(location.search.split("=")[1]) : 1;
const dispatch = useDispatch();
const cart = useSelector((state) => state.cart);
const { cartItems } = cart;
console.log(cartItems);
useEffect(() => {
if (productID) {
dispatch(addToCart(productID, qty));
}
}, [dispatch, productID, qty]);
return (
<>
<h1>Shopping Cart</h1>
</>
);
};
export default CartScreen;
You need to fix this on CartReducer.js
switch (action.state) {
to
switch (action.type) {

I am getting TypeError: this.props.function is not a function while fetching from an api

I am trying to fetch data from an api, but I am getting an error: TypeError: this.props.getPeople is not a function, while everything looks good through the code, as below:
people-component.js
import React, { Component } from 'react';
import './people-component-styles.css';
import { Container, Row, Col, Card } from 'react-bootstrap';
import { connect } from 'react-redux';
import { getPeople } from '../../actions/index'
import 'react-lazy-load-image-component/src/effects/blur.css';
import 'animate.css/animate.min.css';
export class People extends Component {
componentDidMount() {
// console.log(this.props);
this.props.getPeople();
}
render() {
// console.log(this.props);
return (
<Row className='main'>
hello!
</Row>
);
}
}
const mapStateToProps = state => ({
people: state.people
})
const mapDispatchToProps = dispatch => ({
getPeople: () => dispatch(getPeople())
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(People);
actions/index.js
export const getPeople = () => {
console.log("yes");
return async dispatch => {
const response = await fetch('https://dma.com.eg/api.php?action=getPeople', {
method: 'GET'
})
const json = await response.json();
dispatch({ type: "GET_PEOPLE", payload: json });
}
}
reducers/index.js
const INITIAL_STATE = {
people: []
}
const rootReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case "GET_PEOPLE":
return ({
...state,
people: state.people.concat(action.payload)
})
default:
return state;
}
};
export default rootReducer
I was importing People component as name while it's exported as default, thanks to #Brian Thompson .. it's fixed.

Why my "mapDispatchToProps" does not see my action function?

Please tell me why, when I call this.props.getOnEvents(), an error occurs that “getOnEvents() is not a function”, what’s wrong here and how to fix it?
I’m looking at the console.log and there is this function in the props, but when I try to call, an error flies out that it’s not a function
EventCalendar.js
import React, { Component } from 'react';
import { withStyles } from '#material-ui/core/styles';
import EventCalendarTable from './EventCalendarTable';
import EventCalendarView from './EventCalendarView';
const styles = theme => ({
root: {
width: '80%',
margin: '20px auto 0'
},
});
class EventCalendar extends Component {
constructor(props) {
super(props);
this.state = {
viewEvents: 'table'
};
}
componentDidMount() {
this.props.onGetEvents();
}
changeEventsView = (value) => {
this.setState({ viewEvents: value });
}
render() {
console.log(this.props);
const { classes } = this.props;
return (
<div className={classes.root}>
<EventCalendarView changeEventsView={this.changeEventsView}/>
{
this.state.viewEvents === 'table'
? <EventCalendarTable />
: <div>test</div>
}
</div>
);
}
}
export default withStyles(styles)(EventCalendar);
EventPage/component.jsx
import React from 'react';
import EventCalendar from '../../components/EventCalendar';
import './index.scss';
function Events(props) {
return (
<React.Fragment>
<EventCalendar props={props}/>
</React.Fragment>
);
}
export default Events;
EventPage/container.js
import { connect } from 'react-redux';
import EventsPage from './component';
import { getEvents } from '../../../store/modules/Events/operations';
const mapStateToProps = ({ Events }) => ({
Events
});
const mapDispatchToProps = dispatch => ({
onGetEvents: () => {
console.log(123);
dispatch(getEvents());
}
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(EventsPage);
Events/actions.js
import * as types from './types';
export const eventsFetch = value => ({
type: types.FETCHING_EVENTS,
payload: value
});
export const setEvents = ({ objById, arrayIds }) => ({
type: types.SET_EVENTS,
payload: {
eventById: objById,
eventsOrder: arrayIds
}
});
Events/types.js
export const FETCHING_EVENTS = 'Events/FETCHING_EVENTS';
export const SET_EVENTS = 'Events/SET_EVENTS';
Events/operation.js
import FetchClient from 'app/utils/FetchClient';
import IdsAndByIds from 'app/utils/IdsAndByIds';
import { eventsFetch, setEvents } from './actions';
export const getEvents = () => async (dispatch) => {
try {
const { data } = await FetchClient.get('/events');
dispatch(setEvents(IdsAndByIds(data)));
dispatch(eventsFetch(false));
} catch (error) {
console.log(error);
}
};
Events/reducer.js
import { createReducer } from 'store/utils';
import * as types from './types';
const usersInitState = {
fetching: true,
events: {
eventById: null,
usersOrder: null
},
error: null
};
const eventsReducer = createReducer(usersInitState)({
[types.FETCHING_EVENTS]: (state, { payload }) => ({
...state,
fetching: payload
}),
[types.SET_EVENTS]: (state, { payload }) => ({
...state,
events: {
...payload
}
})
});
export default eventsReducer;
Events/index.js
import { combineReducers } from 'redux';
import * as eventsListOperations from './operations';
import reducer from './reducers';
const EventsReducer = combineReducers({
eventsList: reducer
});
export default EventsReducer;
export { eventsListOperations };
The issue here is a minor one, Since you are connecting Events component to connect, you are receiveing the prop onGetEvents in that component, Now inside this component you are passing the props by a name props to the EventCalendar component
<EventCalendar props={props}/>
Now the props in EventCalender will contain a key called as props which wil lhave your data but you are trying to access it directly on props which is why it is undefined.
The correct way to pass the props here would be to use spread syntax like
<EventCalendar {...props}/>

Categories

Resources