React Redux Turbo Module Build Failed - html

I've been following this tutorial (https://www.turbo360.co/tutorial/redux-walkthrough) and I keep trying to run webpack but the build keeps failing. Any one know why it keeps crashing?
import { createStore, appMiddleware, combineReducers } from 'redux'
import thunk from 'redux-thunk'
import { todoReducer } from './reducers'
let store = null
export default {
createStore: () => {
const reducers = combineReducers({
todo: todoReducer
})
store = createStore(
reducers
appMiddleware(thunk)
)
return store
},
currentStore: () => {
return store
}
}
Does anyone know the solution?

You need to import applyMiddleware, not appMiddleware. It's a typo.
applyMiddleware

Related

useFirestoreConnect returns empty object in react redux firebase

I am trying to create a todo app using react redux firebase. I have been able to connect the react redux firebase library to firebase as my create task actions produces changes in the firestore. But the redux store does not seem to be connected to firestore which is why I receive an empty object in console.log when i use fireStoreConnect in the useSelector hook.
store.js
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
// Redux
import { applyMiddleware, legacy_createStore as createStore } from 'redux';
import thunk from 'redux-thunk';
import { getFirebase } from 'react-redux-firebase';
import { getFirestore } from 'redux-firestore';
import { createFirestoreInstance } from 'redux-firestore';
// Reducers
import rootReducer from './reducers/rootReducer';
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: 'AIzaSyDOka0NyhrtvdX3hQihX0yVgHQ3m9f6Alg',
authDomain: 'todo-list-720.firebaseapp.com',
projectId: 'todo-list-720',
storageBucket: 'todo-list-720.appspot.com',
messagingSenderId: '770009943120',
appId: '1:770009943120:web:02fbc5adb060ee2cbc9555',
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
// Initialize Firestore
firebase.firestore();
const rrfConfig = {
userProfile: 'users',
useFirestoreForProfile: true,
};
const store = createStore(
rootReducer,
applyMiddleware(thunk.withExtraArgument({ getFirebase, getFirestore }))
);
const rrfProps = {
firebase,
config: rrfConfig,
dispatch: store.dispatch,
createFirestoreInstance,
};
export { store, rrfProps };
Home.js
import { useSelector } from 'react-redux';
import { useFirestoreConnect } from 'react-redux-firebase';
// Components
import Navigation from '../components/Navigation';
import TaskList from '../components/TaskList';
import AddTask from '../components/AddTask';
const Home = () => {
useFirestoreConnect(['tasks']);
const tasks = useSelector((state) => {
console.log(state.firestore);
return state.firestore.data.tasks;
});
return (
<>
<Navigation />
<AddTask />
<TaskList tasks={tasks} />
</>
);
};
export default Home;
rootReducer.js
import { firebaseReducer } from 'react-redux-firebase';
import { firestoreReducer } from 'redux-firestore';
const rootReducer = combineReducers({
firebase: firebaseReducer,
firestore: firestoreReducer,
/* auth: authReducer, */
tasks: tasksReducer,
});
image of firestore collection
CodeSandbox Link

react-redux-firebase firestore returns function and not object

I'm trying to use firestore with react-redux-firebase on a React App, and when I try to access state.firestore it returns a function and no the object. I'll attach the code for initialization.
This is the app file.
import React from "react";
import ReactDOM from "react-dom";
import "./index.styles.ts";
import * as serviceWorker from "./serviceWorker";
import Theme from "./components/Theme";
import configureStore from "./store/configureStore";
import { Provider } from "react-redux";
import Routes from "routes";
import firebase from 'firebase/app'
import 'firebase/auth';
import 'firebase/firestore';
// import 'firebase/functions' // <- needed if using httpsCallable
import {
ReactReduxFirebaseProvider,
} from 'react-redux-firebase'
import { createFirestoreInstance } from 'redux-firestore';
const firebaseConfig = {
};
// react-redux-firebase config
const rrfConfig = {
userProfile: 'users',
useFirestoreForProfile: true // Firestore for Profile instead of Realtime DB
// enableClaims: true // Get custom claims along with the profile
}
// Initialize firebase instance
firebase.initializeApp(firebaseConfig);
firebase.firestore();
const store = configureStore();
const rrfProps = {
firebase,
config: rrfConfig,
dispatch: store.dispatch,
createFirestoreInstance
};
ReactDOM.render(
<Theme>
<Provider store={store}>
<ReactReduxFirebaseProvider {...rrfProps}>
<Routes />
</ReactReduxFirebaseProvider>
</Provider>
</Theme>,
document.getElementById("root")
);
serviceWorker.unregister();
According to the docs, this is basically what's needed to be able to access firestore.
This is the configureStore file
import { createBrowserHistory } from "history";
import { createStore, applyMiddleware, Store } from "redux";
import { routerMiddleware } from "connected-react-router";
import thunk from "redux-thunk";
import { History } from "history";
import { combineReducers, compose } from "redux";
import { connectRouter } from "connected-react-router";
import * as reducers from "./reducers";
import { firebaseReducer } from "react-redux-firebase";
import { reduxFirestore } from "redux-firestore";
export const history = createBrowserHistory();
const createRootReducer = (history: History<any>) =>
combineReducers({
router: connectRouter(history),
firebase: firebaseReducer,
firestore: reduxFirestore,
...reducers,
});
export default function configureStore(): Store {
const store = createStore(
createRootReducer(history), // root reducer with router state
compose(
applyMiddleware(
routerMiddleware(history), // for dispatching history actions
thunk
)
)
);
return store;
}
Update: As confirmed by #luis, the fix was actually importing firestoreReducer instead of reduxFirestore in the configureStore.ts.
You are setting fiterstore as reduxFirestore, which is imported from redux-firestore library which is indeed a function.
I am not sure if you are using it correctly. Following is usage code from library's npm page:
import { createStore, combineReducers, compose } from 'redux';
import { reduxFirestore, firestoreReducer } from 'redux-firestore';
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/database';
import 'firebase/firestore';
const firebaseConfig = {}; // from Firebase Console
const rfConfig = {}; // optional redux-firestore Config Options
// Initialize firebase instance
firebase.initializeApp(firebaseConfig);
// Initialize Cloud Firestore through Firebase
firebase.firestore();
// Add reduxFirestore store enhancer to store creator
const createStoreWithFirebase = compose(
reduxFirestore(firebase, rfConfig), // firebase instance as first argument, rfConfig as optional second
)(createStore);
// Add Firebase to reducers
const rootReducer = combineReducers({
firestore: firestoreReducer,
});
// Create store with reducers and initial state
const initialState = {};
const store = createStoreWithFirebase(rootReducer, initialState);
Notice how createStoreWithFirebase is called instead of createStore and firestoreReducer is passed along with an initial state.

Unit Testing to see if JSON file is null

I am currently trying to unit test a container that pulls in a static JSON file of phone numbers and passes it to the component to display, however I am not sure how I should go about testing it. The code for the container is as follows:
import React from 'react';
import data from *JSON file location*
import CountryInfo from *component for the country information* ;
class CountryInfoContainer extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
numbersJson: null
};
}
async componentWillMount() {
const numbersJson = data;
this.setState({ numbersJson });
}
render() {
return (
<CountryInfo json={this.state.numbersJson} showText={this.props.showText} />
);
}
}
export default CountryInfoContainer;
I currently have my unit test to look like this
import React from 'react';
import Adapter from 'enzyme-adapter-react-16';
import { mount, configure } from 'enzyme';
import { MemoryRouter } from 'react-router-dom';
import CountryInfoContainer from './CountryInfoContainer';
configure({ adapter: new Adapter() });
describe('Successful flows', () => {
test('checks if json has null entries', () => {
const wrapper = mount(<MemoryRouter><CountryInfoContainer /></MemoryRouter >);
const data = wrapper.find(numbersJson);
// eslint-disable-next-line no-console
console.log(data.debug);
});
});
Obviously, it doesn't work now because I am not sure how to use the variable numbersJson in the container in the test file or how to check if it is null.
The variable numbersJson is not defined in the scope of your test. If I understand correctly, you are testing that when you first mount the component, that it's state contains a null value for the numbersJson key.
First of all, you need to mount your component directly without MemoryRouter:
const wrapper = mount(<CountryInfoContainer />);
Then you can write an expect() for the state:
expect(wrapper.state().numbersJson).toBeNull();

redux persist in the next js project persist:root is not creating localstorage

using the nextjs framework the redux-persist is not creating the local storage values. After login the persist:root is not showing in the local
In the reactjs framework, I have tried the redux persist the persist:root created in the local storage but in the nextjs framework the same method I am following the errors not coming but the persist:root is not showing
in the local storage
//store.js
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducers from './reducers';
import { persistReducer } from 'redux-persist';
import nextConnectRedux from 'next-connect-redux';
import storage from 'redux-persist/lib/storage/session';
const persistConfig = {
key: "root",
storage: storage,
}
const persistedReducer = persistReducer(persistConfig, reducers)
const middleware = [thunk];
const composeEnhancers =
typeof window !== 'undefined' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
}) : compose;
const enhancer = composeEnhancers(
applyMiddleware(...middleware),
);
const store = () => {
return createStore(
persistedReducer,
{},
enhancer
)};
const nextConnect = nextConnectRedux(store)
export default nextConnect;
// index.js
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { persistStore } from 'redux-persist';
import nextConnect from '../store';
import Route from '../routes';
import { BrowserRouter } from "react-router-dom";
class App extends Component {
render () {
const persistor = persistStore(nextConnect);
return (
<Provider store={nextConnect}>
<PersistGate loading={null} persistor={persistor}>
<BrowserRouter>
<Route/>
</BrowserRouter>
</PersistGate>
</Provider>
)
}
}
export default App;
I want the persist:root in the local storage to be showed
if you are rendering React on the server, you cant use redux-persist with default configs
When you are using redux-persist with the default configuration, means you are storing your data on browser storage and you don’t have a browser on the server
The following implementation shows you how to integrate Redux Persist into Next.js
rootReducer.js
store.js
_app.js
That's it
resource
Redux Persist with Next.js

Redux combineReducers with multiple files - making simple mistake

I'm trying to set up a pattern for combining reducers from multiple files as per #gaearon's answer (https://github.com/reduxjs/redux/issues/609#issuecomment-133903294), but am making a simple mistake, and am unable to figure out what it is. Having some brain block on this one... :\
Getting the following error:
Store does not have a valid reducer. Make sure the argument passed to combineReducers is an object whose values are reducers.
My Code:
containers/score/reducers.js
export const goals = (state = 0, action) =>
action.type === types.UPDATE_GOALS ? action.payload : state
export const points = (state = 0, action) =>
action.type === types.UPDATE_POINTS ? action.payload : state
containers/time/reducers.js
export const minutes = (state = 0, action) =>
action.type === types.UPDATE_MINUTES ? action.payload : state
export const seconds = (state = 0, action) =>
action.type === types.UPDATE_SECONDS ? action.payload : state
containers/index.js
import * as score from './score'
import * as time from './time'
export default Object.assign({}, score, time)
store/configureStore.js
import { createStore, combineReducers } from 'redux'
import reducers from '../containers'
const configureStore = initialState =>
createStore(combineReducers(reducers), initialState)
export default configureStore
components/provider.js
import configureStore from '../store/configureStore'
const initialState = { minutes: 55 }
const store = configureStore(initialState)
On large code bases, it won't be enough to just directly import the reducers to the configureStore file. You have these enormous state trees that require hundreds of reducer files, and many reducers import other reducers from other files. Basically I'm asking how to manage a deeply nested state tree of reducers, and combine them one after another using import and export until they reach the root combineReducers function.
If the object passed inside combineReducer is empty or invalid, you'll see that error.
I always structure my reducers this way,
I don't spin off separate export for every action, consolidate them into one export and manage with switch cases.
Each reducer's initialState is defined within the reducer for easy code management.
I've rewritten your code a bit:
containers/score/reducers.js
const initialState = {
goals: 0,
points: 0
};
const scoreReducer = (state = initialState, action) => {
switch (action.type) {
case UPDATE_GOALS:
return { ...state, goals: action.payload };
case UPDATE_POINTS:
return { ...state, points: action.payload };
default:
return state;
}
};
export default scoreReducer;
containers/time/reducers.js
const initialState = {
minutes: 0,
seconds: 0
};
const timeReducer = (state = initialState, action) => {
switch (action.type) {
case UPDATE_MINUTES:
return { ...state, minutes: action.payload };
case UPDATE_SECONDS:
return { ...state, seconds: action.payload };
default:
return state;
}
};
export default timeReducer;
containers/index.js
import score from './score';
import time from './time;
import { combineReducers } from "redux";
const rootReducer = combineReducers({
score,
time
});
export default rootReducer;
And I don't complicate more after this - I just pass the provider and store to my main wrapper component after defining the combined reducers:
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import rootReducer from './container';
import history from './history';
import App from './App';
const store = createStore(
rootReducer
);
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<App />
</Router>
</Provider>,
document.getElementById('root')
);
I really think structuring this way would solve your problem, please try.
It seems like score and time folders don't contain index.js files.
Try to add them or change your containers/index.js file:
import * as score from './score/reducers.js'
import * as time from './time/reducers.js'