Redux-Logger - 'reducer' is not defined
Title.
I'm trying to learn how to use Redux-Logger (dont know whether LogRocket is required, considering it hasnt been updated in years to state its needed but I digress )
According to the usage, the basic implementation is
import { applyMiddleware, createStore } from 'redux';
// Logger with default options
import logger from 'redux-logger'
const store = createStore(
reducer,
applyMiddleware(logger)
)
// Note passing middleware as the third argument requires redux@>=3.1.0
I added that into my code and it tells me
'reducer' is not defined
What am I missing here?
1 answer
-
answered 2022-01-25 09:28
phry
If someone in the future stumbles about this: the documentation of redux-logger shows an outdated example using an outdated style of Redux.
In modern Redux, you would be using
configureStore
instead, as shown by this example from the Redux-Toolkit documentation:import { configureStore } from '@reduxjs/toolkit' import logger from 'redux-logger' import rootReducer from './reducer' const store = configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger), })
do you know?
how many words do you know
See also questions close to this topic
-
Organize large states with redux toolkit
I am fairly new to redux and redux-toolkit, but I am fairly familiar with the whole concept of stores (coming from a vuex background).
I have an issue organizing a large state with lots of dependencies between the objects. My current approach is to use a structure similar to RDBMS where each object has its own ID and other objects reference it through that ID. This way, there are no deeply nested objects.
My current problem is how to organize a large state with lots of dependencies and lots of types of objects (type of object = "table"). I could put all of the objects into a single slice, but this would make that slice incredibly large.
Another approach is to separate each of the object types into different slices, with a single slice for each object type. This presents the problem that accessing the state of another slice is not easily done but is required to update that state in order to keep the state consistent (i.e. avoid broken references).
Is there a good, common approach on how to structure a large state with a lot of dependencies?
-
Add product with Attributes to cart using redux
I need help in Reactjs app 'Add to cart'. I am using redux and to add products to cart with quantity and everything going right until tried to add specific attributes such as size or color and I don't know how to handle this can anyone explain me the logic to do it?
this is the reducer
case actionTypes.ADD_TO_CART: const item = state.data.find((item) => item.id === action.payload.id); const inCart = state.cart.find((item) => item.id === action.payload.id ? true : false ); return { ...state, cart: inCart ? state.cart.map((item) => item.id === action.payload.id ? { ...item, qty: item.qty + 1, selectedAttributes: [...item.selectedAttributes] } : item ) : [...state.cart, { ...item, qty: 1, selectedAttributes: [] }], }; case actionTypes.ADJUST_ATTRIBUTES: let selectedAttributes = []; return { ...state, cart: state.data.map((item) => item.id === action.id ? { ...item, selectedAttributes: { [action.selectedAttributes.name]: action.selectedAttributes.value } } : item ), };
this is action
export const addToCart = (itemID) => { return { type: actionTypes.ADD_TO_CART, payload: { id: itemID } } } export const selectAttribute = (itemID, name, value) => { return { type: actionTypes.ADJUST_ATTRIBUTES, id: itemID, selectedAttributes: { name: name, value: value } } }
this is the radio button I want to select from it to add attribute
attribute.items.map((item, index2) => { return ( <div className="button" key={index2}> <input onClick={() => this.props.selectAttribute( this.props.currentItem.id, attribute.name, item.value ) } type="radio" disabled={!this.props.currentItem.inStock} name={`${this.props.currentItem.name}-${attribute.name}-${index}`} value={item.value} className="attributes-value" /> <label className="attributes-label" htmlFor={`${this.props.currentItem.name}-${attribute.name}-${index}`} > {item.value} </label> </div> ); })
-
Redux Toolkit: How can I store a serialized action creator in state?
Question
I am using Redux Toolkit and I want to store an action creator in state. When I do this, I receive an error regarding non-serializable values in my action as well as my state. Using the code below as an example of my issue, how can I resolve it without just suppressing the warning?
Slice Code
import { ActionCreatorWithoutPayload } from '@reduxjs/toolkit'; export type ModalType = { type: 'MyModal'; actionText: string; onConfirm: ActionCreatorWithoutPayload; } type ui = { modal: ModalType | null; }; const initialState: ui = { modal: null }; export const slice = createSlice({ name: 'ui', initialState: initialState, reducers: { showDialog: (state, action: PayloadAction<ModalType>) => { state.modal= action.payload; }, someAction: (state) => { // do something }, } });
Component Code
import { someAction } from 'reducers/uiSlice'; <Button onClick={() => dispatch( showDialog({ type: 'MyModal', actionText: `Some text`, onConfirm: someAction} ) )} />
Error Message
A non-serializable value was detected in an action, in the state: `payload.onConfirm`. Value: ƒ actionCreator() { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (prepareAction) { var prepared = prepareAction.apply(void…
-
How to maintain global states created dynamically
I am trying to Display list of items with then name and button to download its respective file Same list are available in different other screens. When I click on download
State info sharing: It should start download and the state/progress of the download should be visible to same item available in different other screens.unique identifier is item id
There can be parallel downloads
Problem statement:
- Unable to share the information for same item if we use state within the same item
- On use of redux its solving problem 1 however Parallel download information is getting overwritten as its writing to same reducer state
Any idea or approach is appreciated. Thanks
-
I'm trying to implement Infinite Scrolling in a React application using the IntersectionObserver API but i'm running into some issues
I'm trying to implement infinite scrolling and it's supposed to work by getting data in pages from the API...and then using the IntersectionObserver API, checking for an intersection between the target Element and the viewport, and when there's one, request the next page and get the data and add it to the previous posts...While experimenting I was able to get it to sort of work but it sometimes keeps requesting for the same page and maybe goes into an infinite loop of requests. I was going to try to create a custom hook for it but because I was also using redux I did something like this:
Here's the post component with the infinite scroll implementation:
const Posts = ({ setCurrentId }) => { const classes = useStyles() const dispatch = useDispatch(); const { posts } = useSelector((state) => state.posts); const { numberOfPages } = useSelector((state) => state.posts); const { currentPage } = useSelector((state) => state.posts); const [postsArr, setPostsArr] = useState([posts]); const [hasMore, setHasMore] = useState(false); const [pageNum, setPageNum] = useState(1); useEffect(() => { dispatch(getPosts((pageNum))) const newPostsArr = postsArr.concat(posts); setPostsArr(newPostsArr); setHasMore(numberOfPages > 0); }, [pageNum]); const { loading } = useSelector((state) => state.posts); const observer = useRef(); const lastPostElementRef = useCallback((node) => { if (observer.current) observer.current.disconnect(); observer.current = new IntersectionObserver((entries) => { if (entries[0].isIntersecting && hasMore) { setPageNum((prev) => prev + 1); } dispatch(getPosts(pageNum)); }); if (node) observer.current.observe(node); if (currentPage === numberOfPages) setHasMore(false); }, [hasMore]); if (!postsArr.length && !loading) return 'No posts found'; else return ( <Grid className={classes.container} container alignItems="stretch" spacing={3}> {postsArr[0].map((post, i) => ( (postsArr.length === i + 1) ? ( <Grid key={post._id} ref={lastPostElementRef} item xs={12} sm={6} md={6} lg={3} > <Post post={post} setCurrentId={setCurrentId} /> </Grid> ) : ( <Grid key={post._id} item xs={12} sm={6} md={6} lg={3}> <Post post={post} setCurrentId={setCurrentId} /> </Grid> ) ))} <div>{loading && <CircularProgress />}</div> </Grid> )} export default Posts;
Here's the action that gets dispatched:
export const getPosts = (page) => async (dispatch) => { try { dispatch({ type: START_LOADING }) const { data: { data, currentPage, numberOfPages } } = await api.fetchPosts(Number(page)); dispatch({ type: FETCH_ALL, payload: { data, currentPage, numberOfPages } }); dispatch({ type: END_LOADING }) } catch (error) { console.log(error) } }
And then the reducer:
const postReducer = (state = [], action) => { switch (action.type) { case START_LOADING: return { ...state, loading: true }; case END_LOADING: return { ...state, loading: false }; case FETCH_ALL: return { ...state, posts: action.payload.data, currentPage: action.payload.currentPage, numberOfPages: action.payload.numberOfPages, // error: action.payload.error }; default: return state; } } export default postReducer
I don't think there's a need for this but here's the backend API controller function:
const getPosts = async (req, res) => { const { page } = req.query; try { const LIMIT = 8; const startIndex = (Number(page) - 1) * LIMIT; //GET THE STARTING INDEX OF EVERY PAGE const total = await postMessage.countDocuments({}); const posts = await postMessage.find().sort({ _id: -1 }).limit(LIMIT).skip(startIndex); res.status(200).json({ data: posts, currentPage: Number(page), numberOfPages: Math.ceil(total / LIMIT) }); } catch (error) { res.status(404).json({ message: error.message }); } }
posts and postsArr returns undefined and the component returns this error:
I hope this is detailed enough and I'd really appreciate a response on what I'm doing wrong or if there's a better way to accomplish my goal.
-
Accessing previous state within a useDispatch method
How do I access previous state inside the callback function in react? Because once I access
data
it is always returning an initial state version, since I useuseEffect
only on mountconst data = useSelector(({ state }) => state.data); const dispatch = useDispatch(); useEffect(_ => { dataService.loadData().then(resp => { dispatch({ type: 'SET_DATA', payload: resp.data }); }); }, []); const addData = newData => { dataService.addData(newData).then(_ => { // need the up to date state here for data dispatch({ type: 'SET_DATA', payload: [newData, ...data] }) }); } return <> <button onClick={_ => addData({ name: "new name" })}></button> {data.map(elem => <div>{elem.name}</div>)} </>
-
Redux Thunk payload and action
I do have a Question on Redux + Thunk. I´ve created an Action to call a RestAPI and fetch data from there.
This seems to work but somehow the payload in the State after is missing the responded Data instead it just holds the general Response.
Reducer:
import {REQUEST_CART_FAILED, REQUEST_CART_PENDING, REQUEST_CART_SUCCESS} from "../../reducer-constants"; const INITIAL_STATE = { isPending: false, cartItems: [], error: "" } const cartReducer = (state = INITIAL_STATE, action) => { switch(action.type) { case REQUEST_CART_PENDING: return Object.assign({}, state, { isPending: true} ) case REQUEST_CART_SUCCESS: return Object.assign({}, state, {cartItems: action.payload, isPending: false}) case REQUEST_CART_FAILED: return Object.assign({}, state, {error: action.payload, isPending: false}) default: return state; } } export default cartReducer;
Action:
import {restAPI} from "../../api/restAPI"; import {REQUEST_CART_PENDING, REQUEST_CART_FAILED, REQUEST_CART_SUCCESS} from "../../reducer-constants"; import {hostAPI} from "../../env_dev"; export const setCart = () => (dispatch) => { dispatch({type: REQUEST_CART_PENDING}); restAPI("post", hostAPI + "/cart", {"userid": "1"}) .then(data => dispatch({type: REQUEST_CART_SUCCESS, payload: data})) .catch(error => dispatch({type: REQUEST_CART_FAILED, payload: error})) }
Map and Dispatch:
const mapStateToProps = state => ({ currentUser: state.user.currentUser, cartItems: state.cart.cartItems, isPending: state.cart.isPending, error: state.cart.error }) const mapDispatchToProps = (dispatch) => { return { onRequestCartItems: () => dispatch(setCart()) } }
Call with useEffect:
useEffect(() => { onRequestCartItems() }, [])
Now if I console.log
cartItems
I just see the general Response instead of the Data fetched.Console.log
cartItems
:CARTITEMS: Response {type: 'cors', url: 'http://192.168.10.107:3001/cart', redirected: false, status: 200, ok: true, …} body: (...) bodyUsed: false headers: Headers {} ok: true redirected: false status: 200 statusText: "OK" type: "cors" url: "http://192.168.10.107:3001/cart"
Also I use redux-logger and somehow in the console I see the action from another Redux Action. Action should be e.g.
REQUEST_CART_PENDING
but in the console I do seeREQUEST_PRODUCTS_PENDING
Would be great if someone could point out what I´m missing.
Thanks in Advance!
-
Authentication flow - react native and navigating to and from <AuthStack> <RootStack
I've been reading the React Navigation authentication docs and i can't seem to get my authentication working like the example describes - https://reactnavigation.org/docs/auth-flow/.
I have the following code in my authentication (with redux)
Class App extends Component{ render(){ return ( (this.props.userId == null ? <AuthStack /> : <RootStack />) ) } }
my Redux-Logger is sending me the following message, but as you can see from my console.log, the this.props.userId is coming back as undefined... why?
Here is my ACTION in the auth.js (action) file
export const getUserId = () => { return async dispatch => { await AsyncStorage.getItem('userId').then(userId => { console.log(userId) dispatch(setUserId(userId)) // this.props.navigation.navigate(userId ? 'Main' : 'Login'); }) } }
Here is my REDUCER in the auth.js (reducer) file
const initialState = { userId: '' }; const reducer = (state = initialState, action) => { switch (action.type) { case SET_USERID: return { ...state, userId: action.payload }; case REMOVE_USERID: return { ...state, userId: null }; default: return state; } };