Right now we are using easy peasy in our project, now we want to remove easy peasy store gradually and replace it with reduxtoolkit. Can we use stores with different libraries in react? Or is any alternative way to deal with this situation.
Tried below which is not working:
**Creating store out of reduxtoolkit**
import { configureStore,combineReducers } from "#reduxjs/toolkit";
import appReducer from "./slice/appReducer";
const rootReducer= combineReducers({
app: appReducer,
});
const store = configureStore({
reducer: rootReducer,
});
**For easy peasy**
import models from './models';
import { createStore } from 'easy-peasy';
const store = createStore(models);
**In main file**
<Provider store={store }>
<Provider store={reduxStore }>
<App/>
</Provider>
</Provider>
**It is failing with Error:**
easy-peasy.esm.js:93 Uncaught TypeError: store.getActions is not a function
Basically Missing step from my side was Importing Provider from correct package.
import { Provider as ReduxProvider } from "react-redux";
import { StoreProvider as Provider } from 'easy-peasy';
<ReduxProvider store={reduxStore }>
<Provider store={easyPeasystore }>
Changing my code with above line helped me in solving problem.
Related
I'm currently trying to use React + Typescript + Redux and I'm running into an issue. I'm trying to test the Redux Store setup via chrome devTools. I know I butchered the code (very new to Typescript) and I'm getting this error 'Uncaught TypeError: Cannot read properties of undefined (reading 'dispatch')' every time I test it. I tried declaring a global window state, installed redux-dev-tools, but still very lost.
This is what my store/index.tsx file look like:
import {
legacy_createStore as createStore,
combineReducers,
applyMiddleware,
compose,
StoreEnhancer,
} from "redux";
import { devToolsEnhancer } from "redux-devtools-extension";
import thunk from "redux-thunk";
const rootReducer = combineReducers({});
let enhancer;
if (process.env.NODE_ENV === "production") {
enhancer = applyMiddleware(thunk);
} else {
const logger = require("redux-logger").default;
const composeEnhancers =
(window && (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
enhancer = composeEnhancers(applyMiddleware(thunk, logger));
}
const configureStore = () => {
return createStore(rootReducer, devToolsEnhancer({}));
};
export default configureStore;
and my types/index.d.ts:
import { StoreEnhancer } from 'redux'
export {};
declare global {
interface Window {
store: {};
__REDUX_DEVTOOLS_EXTENSION__?: () => StoreEnhancer;
}
}
And finally my src/index.tsx:
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import configureStore from "./store";
const store = configureStore();
if (process.env.NODE_ENV !== "production") {
window.store = store;
};
function Root() {
return (
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
}
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<React.StrictMode>
<Root />
</React.StrictMode>
);
I will also attach screenshots of my file setup:
And my console error:
I am open to all suggestions, thank you!
The first issue here is that the store setup code is using outdated patterns and a lot of handwritten code. Today, you should be using our official Redux Toolkit package to write your Redux apps, and as part of that, RTK's configureStore API. It does all that same work with just a few lines:
import { configureStore } from "#reduxjs/toolkit";
const store = configureStore({
reducer: {
posts: postsReducer,
comments: commentsReducer
}
})
That automatically combines reducers, adds the Redux DevTools extension setup, and adds the thunk middleware.
See our docs for guidance on setup:
https://redux.js.org/tutorials/quick-start
https://redux.js.org/tutorials/typescript-quick-start
https://redux.js.org/introduction/why-rtk-is-redux-today
https://redux.js.org/tutorials/essentials/part-2-app-structure
As for the specific error message you're seeing... the code seems like it would run. My guess is that something is wrong with the process.env.NODE_ENV check you added and so it's not assigning window.store.
RTK also works much better with TypeScript than legacy Redux code does.
So I have been creating an application where a user needs to log into firebase using google authentication. I am using redux, react-redux, react-redux-firebase, redux-firestore, and redux-thunk. I am able to successfully log the user into firebase with the google authentication. I now want to use firestore in order to have a collection of all the users. I have looked at the documentation for redux-firestore and the method of getting/manipulating is a little different. I have tried using the documentation, but I cannot get the functions to work with redux-firestore.
Here is the action
export const signIn = () => (
dispatch,
getState,
{getFirebase, getFirestore}) => {
const firebase = getFirebase();
const firestore = getFirestore();
firebase.auth().signInWithPopup(provider).then(function(result) {
if(result.credential) {
firestore.get({collection: 'users', doc: result.user.uid}).then(function(doc) {
if(!doc.exists){
console.log("new!")
firestore.add(
{collection: 'users', doc: result.user.uid},
{name: firebase.auth.currentUser.displayName});
} else{
console.log("old!")
}
})
}
}).catch((err) => {
})
};
And here is my setup in index.js for the src folder
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {BrowserRouter} from 'react-router-dom';
import {createStore, applyMiddleware, compose} from 'redux';
import {Provider} from 'react-redux';
import allReducers from './reducers';
import thunk from 'redux-thunk';
import firebase from './Firebase';
import {firebaseConfig} from './Firebase'
import {createFirestoreInstance, getFirestore, reduxFirestore} from 'redux-firestore';
import {ReactReduxFirebaseProvider, getFirebase} from 'react-redux-firebase';
const store = createStore(
allReducers,
compose(
applyMiddleware(thunk.withExtraArgument({getFirebase, getFirestore})),
reduxFirestore(firebaseConfig)
));
const rrfConfig = {
userProfile: 'users',
useFirestoreForProfile: true
};
const rrfProps = {
firebase,
config: rrfConfig,
dispatch: store.dispatch,
}
ReactDOM.render(
<Provider store={store}>
<ReactReduxFirebaseProvider {...rrfProps}>
<BrowserRouter>
<App />
</BrowserRouter>
</ReactReduxFirebaseProvider>
</Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
I know that I have not used createFirestoreInstance in this code, but I was playing around with it.
If anyone could tell me how to get this working, I would appreciate it.
Thanks!
Quick update:
I have figured out how to at least write to firestore using this code
const userRef = firebase.firestore().collection('users').doc(result.user.uid);
userRef.get().then(function(doc) {
if(!doc.exists){
userRef.set({name: result.user.displayName});
}
})
This is not the best (or maybe the right solution), but it does work. It is not using redux-firestore, but is there a better way?
If you're using React, use react-redux-firebase. There's no need for these many complication and the code looks much neater and simpler. Authentication, firestore and all other firebase features works out of the box with just small amount of code. They also comes with React hooks like useFirebase() and useFirestore() instead of you needing to write them on your own.
react-redux-firebase is built on top of redux-firebase and provides all the things you would need in React.
If your app only uses firebase, I would even recommend you use just plain Redux without Redux Thunk or Redux Saga.
Iam new to learning Redux.
When i write store.subscribe(render) my app compiles without errors but nothing shows up.
I've been following an article(https://medium.freecodecamp.org/understanding-redux-the-worlds-easiest-guide-to-beginning-redux-c695f45546f6) that beautifully explains redux but that subscribe part is just not working.
Any help in this regard will be very much appreciated.
I tried everything i could i even rebuilt the app but no luck.
index.js
./reducer/index.js
./store/index.js
App.js
First, try changing line 17 of App.js from
<HelloWorld tech={this.state.tech}/>
to:
<HelloWorld tech={store.getState().tech}/>
Else, try putting a constructor into your App component:
constructor(props) {
super(props);
store.subscribe(() => {
this.setState({
tech: store.getState().tech
});
});
}
You need to add a provider into your store to subscribe the changes.
For more details please check this link https://react-redux.js.org/api/provider
Please find the sample code for the store.
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import { App } from './App'
import createStore from './createReduxStore'
const store = createStore()
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
You have to import createStore.
import { createStore } from 'redux';
Then you will need to make the store variable and pass in the reducer.
const store = createStore(yourReducer);
Then your reducer will look something like this.
const initState = {
}
const yourReducer = (state = initState, action) => {
return state;
}
export default yourReducer
I'm building a React Native app with TypeScript using Redux for my state.
I like using two seperate files for configureStore. In JS This looks like this:
configureStore.dev.js:
import { applyMiddleware, createStore } from "redux";
import logger from "redux-logger";
import reducers from "../reducers";
const configureStore = () => {
const store = createStore(reducers, applyMiddleware(logger));
return store;
};
export default configureStore;
configureStore.prod.js:
import { createStore } from "redux";
import reducers from "../reducers";
const configureStore = () => {
const store = createStore(reducers);
return store;
};
export default configureStore;
configureStore.js:
import Config from "react-native-config";
if (Config.REACT_ENVIRONMENT === "staging") {
module.exports = require("./configureStore.dev");
} else {
// tslint:disable-next-line no-var-requires
module.exports = require("./configureStore.prod");
}
And then within App.js:
import React, { Component } from "react";
import Orientation from "react-native-orientation";
import { Provider } from "react-redux";
import Navigator from "./navigation/Navigator";
import configureStore from "./redux/store/configureStore";
export const store = configureStore();
export default class App extends Component {
componentDidMount = () => {
Orientation.lockToPortrait();
};
render() {
return (
<Provider store={store}>
<Navigator />;
</Provider>
);
}
}
The problem now with TypeScript is that - after converting these files to .ts and .tsx - this code throws linting errors (and it furthermore blocks all Jest unit tests from running).
The lines where modules.exports exports the respective file depending on environment variables throws the error:
[tslint] require statement not part of an import statement (no-var-requires)
And in App.tsx the import of configureStore throws:
[ts] Module '"/Users/jan/Documents/FullStackFounders/PainButton/painbutton/app/redux/store/configureStore"' has no default export.
How would one handle this case in TypeScript?
The only solution I could come up with was only using one file and using a lot of if's for all the Dev only configs. But that doesn't seem clean to me.
It seems you are mixing import / export and require / module.exports syntax.
Try to use dynamic import expressions.
configureStore.js
export default Config.REACT_ENVIRONMENT === "staging" ? import("./configureStore.dev") : import("./configureStore.prod");
main render file
import configure from "./configureStore.js";
configure.then(configFunc => {
const store = configFunc();
ReactDOM.render(<App store={store} />, document.querySelector("#root"));
})
Pass the store as a prop to the <App /> Component.
I hope it will help.
OK - what the heck am I missing... spent a day and a half trying to solve this and am about to ditch redux...
I have the following root route...
...
import configureStore from 'NewApp/client/store';
import createBrowserHistory from 'history/lib/createBrowserHistory';
const history = createBrowserHistory();
const store = configureStore(history);
ReactDOM.render(
<Provider store={store}>
<Router
history={history}
children={routes}
{...clientOptions.props} />
</Provider>
, rootElement
);
...
And I see the store object, but I keep getting an error saying it's not there...
Adding requested additional code:
...
import rootReducer from '../reducers';
const middlewares = [
thunkMiddleware,
loggerMiddleware,
];
const finalCreateStore = compose(
applyMiddleware(...middlewares),
window.devToolsExtension ? window.devToolsExtension() : f => f
)(createStore);
export default function configureStore(history, initialState) {
const store = finalCreateStore(rootReducer, initialState);
syncReduxAndRouter(history, store, state => state.router);
return store;
}
...
...
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { clearNotification } from '../actions/notifications';
import { logout } from '../actions/auth';
import App from '../components/App';
function mapStateToProps(state) {
return {
locale: state.app.locale,
loggingIn: state.auth.loggingIn,
messages: state.app.messages,
notification: state.notification,
title: state.app.title,
user: state.auth.user,
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
clearNotification,
logout,
}, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
OK, here's the deal... it turns out that the demo app I am using code splits and if you add flux/redux into the mix in additional to all the 'joy' redux has already given, you actually need to 'split' your reducers as well per this repo.
The original error in my question above happened going to any non-root route because webpack code splitting makes those router calls async - basically getting things out of kilter with the reducer(s) in the store. The repo linked to in this answer shows how to keep the router and store in sync with the 'dynamic' reducers.
Am I the only one starting to feel like adding in redux is becoming more work than writing an entire large, complex app in the first place? Seeing those redux 10 line 'counter' app demos made it look so... easy? Anyway, hopefully this unveiling which by the way is not well documented in redux yet can help someone in the future!