TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator) - javascript

What I'm doing wrong. Below is my code.
// Imports
import { getAuth, signInWithPopup, GoogleAuthProvider } from "firebase/auth";
import { app } from "../../firebase.config";
import { useStateValue } from "../../context/StateProvider";
import { actionType } from "../../context/Reducer";
const firebaseAuth = getAuth(app);
const googleAuthProvider = new GoogleAuthProvider();
const [{user}, dispatch] = useStateValue();
const [isMenu, setIsMenu] = useState(false);
const login = async () => {
// const response = await signInWithPopup(firebaseAuth, googleAuthProvider);
// console.log(response);
if (!user) {
const {
user: { refreshToken, providerData },
} = await signInWithPopup(firebaseAuth, googleAuthProvider);
dispatch({
type: actionType.SET_USER,
user: providerData[0],
});
localStorage.setItem("user", JSON.stringify(providerData[0]));
} else {
setIsMenu(!isMenu);
}
};
// StateProvider.js
import React, {createContext , useContext, useReducer } from 'react';
export const StateContext = createContext();
export const StateProvider = ({Reducer,InitialState,children}) => (
<StateContext.Provider value = {useReducer(Reducer,InitialState)} > {children} </StateContext.Provider>
)
export const useStateValue = () => useContext(StateContext);
// reducer.js
export const actionType = {
SET_USER : 'SET_USER'
}
export const Reducer = (state, action) => {
// console.log(action);
switch(action.type) {
case actionType.SET_USER:
return {
...state,
user: action.user,
};
default:
return state;
}
}
// InitialState.js
import { fetchUser } from '../utils/fetchUserFromLocalStorage';
const userInfo = fetchUser();
export const InitialState = {
user : userInfo
}
// Error I'm getting
Header.jsx:31 Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
at Header (Header.jsx:31:1)
at renderWithHooks (react-dom.development.js:16305:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27451:1)
at performUnitOfWork (react-dom.development.js:26557:1)
at workLoopSync (react-dom.development.js:26466:1)
I had imported every thing perfectly also used it coorect way. My page isn't rendering anything. It is compiled perfectly with 0 error. Error i'm getting is typeerror but i didn't see any type erro. Please help me.

Related

React-redux error: Uncaught Type Error _store_index_js__WEBPACK_IMPORTED_MODULE_2_is not a function

I am a newbie to Redux. I am trying a counter using redux but when I try to increase or decrease the counter using the increment/decrement buttons, I encounter this error:
Uncaught TypeError: _store_index_js__WEBPACK_IMPORTED_MODULE_2__.default.increment is not a function
at increment (App.js:10:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4291:1)
at executeDispatch (react-dom.development.js:9041:1)
at processDispatchQueueItemsInOrder (react-dom.development.js:9073:1)
at processDispatchQueue (react-dom.development.js:9086:1)
at dispatchEventsForPlugins (react-dom.development.js:9097:1)
at react-dom.development.js:9288:1
The state of the counter value does not change.
App.js
import { useSelector, useDispatch } from 'react-redux';
import './App.css';
import actions from './store/index.js';
function App() {
const counter = useSelector((state) => state.counter);
const dispatch = useDispatch();
const increment = ()=> {
dispatch(actions.increment());
}
const decrement = () => {
dispatch(actions.decrement());
}
const addBy = () => {
dispatch(actions.addBy(10))
}
return (
<div>
<h1>Counter App</h1>
<h2>{counter}</h2>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={addBy}>Add By 10</button>
</div>
);
}
index.js
import { configureStore, createSlice } from '#reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState : { counter: 0 },
reducers: {
increment(state, action) {
state.counter++;
},
decrement(state, action) {
state.counter--;
},
addBy(state, action) {
state.counter += action.payload;
}
}
})
export const actions = counterSlice.actions;
const store = configureStore({
reducer: counterSlice.reducer
})
export default store;
What am I missing? Your help is highly appreciated.
Should be
import { actions } from './store/index.js';

I am getting an error "Uncaught TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))". Unable to find solution

const Header = () => {
const firebaseAuth = getAuth(app);
const provider = new GoogleAuthProvider();
const [{user}, dispatch] = useStateValue();
const login = async () =>{
const {
user: { refreshToken, providerData },
} = await signInWithPopup(firebaseAuth, provider);
dispatch({
type: actionType.SET_USER,
user: providerData[0],
});
};
import React, { createContext, useContext, useReducer } from "react";
export const StateContext = createContext();
export const StateProvider = ({ reducer, initialState, children }) => (
// initial state is already defined as user : null
// children is basically our component
<StateContext.Provider value={useReducer(reducer, initialState)}>
{children}
</StateContext.Provider>
);
// Custome Hook
export const useStateValue = () => {
useContext(StateContext);
};
I am using context api to create a data layer at the top of all components. But I am trying that when the user logged in the user information stored in a state and gets updated. But here I am getting an error at const [{user}, dispatch] = useStateValue();
The problem was in where useStateValue was defined. I actually mistakenly add curley braces while making a custom hook

Firebase createUserProfileDocument() is returning undefined

the createUserProfileDocument() method from firebase is returning undefined for some reason, therefore, it's throwing an error on my broswer's console.
The error thrown is:
App.js:23 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'onSnapshot') at App.js:23:1
the code:
import React from 'react';
import './App.css';
import { connect } from 'react-redux';
import { Switch, Route } from 'react-router-dom';
import HomePage from './pages/homepage/homepage.component';
import ShopPage from './pages/shop/shop.component';
import Header from './components/header/header.componet';
import { auth, createUserProfileDocument } from './firebase/firebase.utils';
import SignInAndSignUpPage from './pages/sign-in-and-sign-up/sign-in-and-sign-up.component';
import { setCurrentUser } from './redux/user/user.actions';
class App extends React.Component {
unsubscribeFromAuth = null;
componentDidMount() {
const { setCurrentUser } = this.props;
this.unsubscribeFromAuth = auth.onAuthStateChanged(async (userAuth) => {
if (userAuth) {
const userRef = await createUserProfileDocument(userAuth);
console.log(userRef);
userRef.onSnapshot((snapshot) => {
setCurrentUser({
id: snapshot.id,
...snapshot.data(),
});
});
}
setCurrentUser(userAuth);
});
}
componentWillUnmount() {
this.unsubscribeFromAuth();
}
render() {
return (
<div className='App'>
<Header />
<Switch>
<Route exact path='/' component={HomePage} />
<Route exact path='/shop' component={ShopPage} />
<Route
exact
path='/signin'
component={SignInAndSignUpPage}
/>
</Switch>
</div>
);
}
}
const mapDispatchToProps = (dispatch) => ({
setCurrentUser: (user) => dispatch(setCurrentUser(user)),
});
export default connect(null, mapDispatchToProps)(App);
The portion of code related to my error is the following:
componentDidMount() {
const { setCurrentUser } = this.props;
this.unsubscribeFromAuth = auth.onAuthStateChanged(async (userAuth) => {
if (userAuth) {
const userRef = await createUserProfileDocument(userAuth);
console.log(userRef);
userRef.onSnapshot((snapshot) => { // This is Line 23......
setCurrentUser({
id: snapshot.id,
...snapshot.data(),
});
});
}
setCurrentUser(userAuth);
});
}
I console.logged(userRef) as you can see, and it returns undefined. This is my first experience with firebase so I am not sure where the error is.
I googled and found an answer here in stackoverflow which is alike to my issue: TypeError: Cannot read properties of undefined (reading 'onSnapshot')
However, that problem is specifically related to how the developer was passing the method as an array and not a method, which does not help my situation.
EDIT: Adding firebase.utils code.
import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import 'firebase/compat/auth';
const config = {
apiKey: 'AIzaSyDxUMY8sUpOMAoxEyHo41ONilzjL2woWHk',
authDomain: 'crown-db-d4416.firebaseapp.com',
projectId: 'crown-db-d4416',
storageBucket: 'crown-db-d4416.appspot.com',
messagingSenderId: '887003208895',
appId: '1:887003208895:web:778f8f55a0ad2c72953a0a',
measurementId: 'G-6TGCRVN7D3',
};
export const createUserProfileDocument = async (userAuth, additionalData) => {
if (!userAuth) return;
const userRef = firestore.doc(`users/${userAuth.uid}`);
const snapShot = await userRef.get();
console.log(snapShot);
if (!snapShot.exists) {
const { displayName, email } = userAuth;
const createdAt = new Date();
try {
await userRef.set({
displayName,
email,
createdAt,
...additionalData,
});
} catch (error) {
console.log('Error creating user: ', error.message);
}
}
};
firebase.initializeApp(config);
export const auth = firebase.auth();
export const firestore = firebase.firestore();
const googleProvider = new firebase.auth.GoogleAuthProvider();
export const signInWithGoogle = () => {
auth
.signInWithPopup(googleProvider)
.then((res) => {
console.log(res.user);
})
.catch((error) => {
console.log(error.message);
});
};
export default firebase;
Your createUserProfileDocument function doesn't return anything, so that explains why this code then fails:
const userRef = await createUserProfileDocument(userAuth);
console.log(userRef);
userRef.onSnapshot((snapshot) => {
The solution is to return the userRef from createUserProfileDocument as your calling code expects:
export const createUserProfileDocument = async (userAuth, additionalData) => {
...
return userRef;
};

problem connecting multiple container components to redux store

I'm having trouble connecting my container components to the redux store, I'm not sure exactly where the connection is supposed to happen, whether in the container component or the component that will be dispatching an action. currently, my index.js looks like this
import React from "react";
import reactDOM from "react-dom";
import App from "./app.jsx";
import storeFactory from "./store";
import { Provider } from 'react-redux';
const store = storeFactory();
reactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("app")
);
currently, my store factory function looks like this
import rootReducer from "../reducers";
import { createStore, applyMiddleware } from "redux";
import { fetchProductInformation } from "../actions";
const storeData = {
productInformation: {}
};
const storeFactory = (initialState = storeData) => {
applyMiddleware(fetchProductInformation)(createStore)(
rootReducer,
localStorage["redux-store"]
? JSON.parse(localStorage["redux-store"])
: storeData
);
};
export default storeFactory;
my container component is
import SearchBar from '../components/searchbar.jsx';
import Nutrients from "../components/Nutrients.jsx";
import { fetchProductInformation } from '../actions';
import { connect } from 'react-redux';
const newSearch = (props) => (
<SearchBar
className="searchbar searchbar_welcome"
onNewProduct={( name ) => (props.fetchProductInformation(name))}
/>
)
const productInformation = (props) => {
const { nutrients, name } = props;
return nutrients.length > 1 ?
(
<div>
<newSearch />
<h3>{name}</h3>
<hr/>
<Nutrients
className="nutrientInformation"
list={nutrients}
/>
</div>
)
: null
}
const mapStateToProps = ({nutrients, name}) => ({
nutrients,
name
});
const mapDispatchToProps = dispatch => ({
fetchProductInformation: name => {
dispatch(fetchProductInformation(name))
}
});
export const Search = connect(null, mapDispatchToProps)(newSearch);
export const productInfo = connect(mapStateToProps)(productInformation);
when i run the code i get the following error
Provider.js:19 Uncaught TypeError: Cannot read property 'getState' of undefined
at Provider.js:19
at mountMemo (react-dom.development.js:15669)
at Object.useMemo (react-dom.development.js:15891)
at useMemo (react.development.js:1592)
at Provider (Provider.js:18)
at renderWithHooks (react-dom.development.js:15108)
at mountIndeterminateComponent (react-dom.development.js:17342)
at beginWork$1 (react-dom.development.js:18486)
at HTMLUnknownElement.callCallback (react-dom.development.js:347)
at Object.invokeGuardedCallbackDev (react-dom.development.js:397)
react-dom.development.js:19814 The above error occurred in the <Provider> component:
in Provider
Consider adding an error boundary to your tree to customize error handling behavior.
Visit react-error-boundaries to learn more about error boundaries.
Provider.js:19 Uncaught TypeError: Cannot read property 'getState' of undefined
at Provider.js:19
at mountMemo (react-dom.development.js:15669)
at Object.useMemo (react-dom.development.js:15891)
at useMemo (react.development.js:1592)
at Provider (Provider.js:18)
at renderWithHooks (react-dom.development.js:15108)
at mountIndeterminateComponent (react-dom.development.js:17342)
at beginWork$1 (react-dom.development.js:18486)
at HTMLUnknownElement.callCallback (react-dom.development.js:347)
at Object.invokeGuardedCallbackDev (react-dom.development.js:397)
from the errors shown i dont know exactly what the error is as it seems to be comming from the provider.js..
your code has some bug. here are fixed code.
import SearchBar from '../components/searchbar.jsx';
import Nutrients from "../components/Nutrients.jsx";
import { fetchProductInformation } from '../actions';
import { connect } from 'react-redux';
const newSearch = (props) => (
<SearchBar
className="searchbar searchbar_welcome"
onNewProduct={( name ) => (props.fetchProductInformation(name))}
/>
)
const productInformation = (props) => {
const { nutrients, name } = props;
return nutrients.length > 1 ?
(
<div>
<newSearch />
<h3>{name}</h3>
<hr/>
<Nutrients
className="nutrientInformation"
list={nutrients}
/>
</div>
)
: null
}
const mapStateToProps = ({nutrients, name}) => ({
nutrients,
name
});
const mapDispatchToProps = dispatch => ({
fetchProductInformation: name => {
dispatch(fetchProductInformation(name))
}
});
export const Search = connect(null, mapDispatchToProps)(newSearch);
export const productInfo = connect(mapStateToProps)(productInformation)
store.js
import rootReducer from "../reducers";
import { createStore } from "redux";
const storeData = {
productInformation: {}
};
const initialStore = localStorage["redux-store"] ? JSON.parse(localStorage["redux-store"]) : storeData;
const store = createStore(rootReducer, initialStore);
export default store;
index.js
import store from "./store";
...
<Provider store={store}>
...

async redux. Error: modifiers may not emit actions

I keep encountering what appears to be a parallel async redux error. At a high level I am trying to dispatch a bunch of async actions that fetch assets from urls.
I originally tried redux-thunk middleware and was encountering the same error. I have since moved to a "listener" style middleware which looks like:
// listener-middleware.js
// taken from https://medium.com/#alexandereardon/the-middleware-listener-pattern-better-asynchronous-actions-in-redux-16164fb6186f
export default (...listeners) => store => next => action => {
// listeners are provided with a picture
// of the world before the action is applied
const preActionState = store.getState();
// release the action to reducers before
// firing additional actions
next(action);
// always async
setTimeout(() => {
// can have multiple listeners listening
// against the same action.type
listeners.forEach(listener => {
if (listener[action.type]) {
listener[action.type](action, store.dispatch, preActionState);
}
});
});
};
The asset listener then looks like:
import { assetsFetchBinary, assetsReceiveBinary } from '../assets/actions.js';
export default {
[assetsFetchBinary.toString()]: (action, dispatch, state) => {
const assetPath = state.config.assetPath + '/' + action.payload.assetName;
if(!state.assets[action.payload.assetName]){
fetch(assetPath)
.then(response => response.arrayBuffer())
.then(arrayBuffer => {
return dispatch(assetsReceiveBinary(action.payload.assetName, arrayBuffer))
});
}
},
}
The store configuration and applyMiddleware is:
import { createStore, applyMiddleware } from 'minidux'
import rootReducer from './rootReducer';
import { createLogger } from 'redux-logger';
import { routerMiddleware } from 'react-router-redux'
import { sceneTickAction } from './dsl/scene/actions.js';
import assetMiddleware from './dsl/assets/middleware.js';
import listenerMiddleware from './listener-middleware';
const logger = (initialState) => {
const predicate = (getState, action) => {
if(action.type === sceneTickAction.toString()){
return false;
}
return true;
}
return createLogger({predicate});
};
const getMiddleWare = (initialState, history) => {
const list = [];
if(initialState.system.role === 'client'){
const routerHistory = routerMiddleware(history);
list.push(routerHistory);
list.push(listenerMiddleware(assetMiddleware))
list.push(logger(initialState));
return list;
};
const configureStore = (initialState, history) => {
return createStore(
rootReducer(initialState),
initialState,
applyMiddleware.apply(this, getMiddleWare(initialState, history))
);
}
export default configureStore
The actions are straight forward
import { createAction } from 'redux-actions';
export const assetsReceiveBinary = createAction('#ASSETS/RECEIVE_BINARY')
export const assetsFetchBinary = createAction('#ASSETS/FETCH_BINARY')
and the Reducers:
import { handleActions } from 'redux-actions';
import { assetsFetchBinary, assetsReceiveBinary } from '../assets/actions.js';
export const assetReducer = (state, action) => handleActions({
[assetsFetchBinary]: (state, action) => {
if(state.assets[action.path]){ return state; }
return {
...state,
assets: {
...state.assets,
[action.path]: {}
}
}
},
[assetsReceiveBinary]: (state, action) => {
return {
...state,
assets: {
...state.assets,
[action.path]: {arrayBuffer: action.arrayBuffer}
}
}
}
}, state)(state, action);
export default assetReducer;
The stack trace is as follows:
createStore.js:27 Uncaught Error: modifiers may not emit actions
at dispatch (createStore.js:27)
at listener-middleware.js:10
at middleware.js:13
at Object.assetsFetchBinary (bindActionCreators.js:3)
at CharacterView.jsx:21
at Array.forEach (<anonymous>)
at CharacterView.componentDidUpdate (CharacterView.jsx:20)
at commitLifeCycles (react-dom.development.js:11517)
at commitAllLifeCycles (react-dom.development.js:12294)
at HTMLUnknownElement.callCallback (react-dom.development.js:1299)
at Object.invokeGuardedCallbackDev (react-dom.development.js:1338)
at invokeGuardedCallback (react-dom.development.js:1195)
at commitAllWork (react-dom.development.js:12415)
at workLoop (react-dom.development.js:12687)
at HTMLUnknownElement.callCallback (react-dom.development.js:1299)
at Object.invokeGuardedCallbackDev (react-dom.development.js:1338)
at invokeGuardedCallback (react-dom.development.js:1195)
at performWork (react-dom.development.js:12800)
at scheduleUpdateImpl (react-dom.development.js:13185)
at scheduleUpdate (react-dom.development.js:13124)
at Object.enqueueSetState (react-dom.development.js:9646)
at Connect../node_modules/react/cjs/react.development.js.ReactComponent.setState (react.development.js:
dispatch line 27 looks like:
function dispatch (action) {
if (!action || !isPlainObject(action)) throw new Error('action parameter is required and must be a plain object')
if (!action.type || typeof action.type !== 'string') throw new Error('type property of action is required and must be a string')
if (isEmitting) throw new Error('modifiers may not emit actions')
The action at that dispatch call looks like {type: "#ASSETS/FETCH_BINARY"}
Additionally, I invoke these actions in componentDidMount like the following:
class CharacterView extends Component {
componentDidUpdate(){
if(this.props.missingItemAssets){
this.props.missingItemAssets.forEach((assetName) => {
this.props.assetsFetchBinary(assetName);
});
}
}
If I wrap the dispatch calls in a 0 setTimeout it prevents the error.
class CharacterView extends Component {
componentDidUpdate(){
if(this.props.missingItemAssets){
setTimeout(() => {
this.props.missingItemAssets.forEach((assetName) => {
this.props.assetsFetchBinary(assetName);
});
}, 0)
}
}
You mentioned that you dispatch the actions in componentDidMount, but your example shows you're actually dispatching from componentDidUpdate.
class CharacterView extends Component {
componentDidUpdate(){ // <--- should be componentDidMount?
if(this.props.missingItemAssets){
this.props.missingItemAssets.forEach((assetName) => {
this.props.assetsFetchBinary(assetName);
});
}
}
}
This might be causing your problem, assuming your example in the question is accurate.

Categories

Resources