If I'm already using next-auth within my next.js app can I add redux around it inside _app.js somehow?
what i tried is this:
import React from "react"
import { Provider } from 'next-auth/client'
import {Provider as ReduxProvider} from 'react-redux';
import {configureStore} from './store/configureStore';
import '../public/styles.css'
const store = configureStore();
export default function App ({ Component, pageProps }) {
return (
<ReduxProvider store={store}>
<Provider
// next-auth params, etc.
is this correct? does it work this way?
i'll also need to use redux-saga, new to the whole thing so i'm at a setup stage yet
The answer is YES. You can do that. I've tried myself and it works perfectly.
Related
I'm was making the shopping card Project and I decide to use Contextapi and useReducer for my state management at the start of my project I wrap the App in context Api and it crash my App Here is the Code.
****Main Index *******
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import Context from "./Context";
ReactDOM.render(
<React.StrictMode>
<Context>
<App />
</Context> </React.StrictMode>,
document.getElementById("root")
);
**** Context Api******
import { createContext } from "react";
const Card = createContext();
const Context = ({ childern }) => {
return <Card.Provider>{childern}</Card.Provider>;
};
export default Context;
Just a guess because you didn't provide enough information on the error but you could try moving the context initialization to a separate module and just import it where you need it.
I ran into a strange runtime issue when I initialized it in a UI component.
You need to pass a value prop to context provider without that there is no point of using context API.
As you have mentioned you are using useReducer , an example would be like below to pass the state to the children.
const Context = ({ childern }) => {
const [state,dispatch] = useReducer(reducer,initialState)
return <Card.Provider value={state}>{childern}</Card.Provider>;
};
I have a react app that uses sessions with an express server using REST API.
In my Redux store(on the front end) I store "isLoggedIn" in the redux state. Based on that property I show either the login page , or the home page. Now when I open the website, the initial redux "isLoggedIn" state is false, so the question is, how do I check if the user is actually logged in. I am thinking about sending a request to the endpoint for fetching the data I need in the homepage, and if the user is not logged in, I would get an 401 response and then show the login page. Is this the correct approach?
Before I get into how you could persist your redux state I would advise(Note This is a personal view)
Going through the boiler plate code of setting that up is really unnecessarily long
Best way out for this is using express-session whereby the cookie is persisted for as long as you gave it e.g if you set cookie to be 3days it will stay for 3days
I so believe that it's industry standard working with httpOnly cookie for session handling as this is secure avoiding XSS attacks and CSRF attacks
Either way below is your solution to persisting Redux Store
So with persisting your redux state you can look into something like this
First run npm install redux-persist or yarn add redux-persist
Now time to create your redux store
So now when you create your redux store with createStore you want to pass your createStore function a persistReducer Once your store is created, pass it to the persistStore function, which will make sure that your redux state is persisted
Implementation below
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import rootReducer from './reducers';
//Import above comes from a file **reducers** which has the combineReducers
// basically based on this code snippet
// I have my combineReducer object in another folder hope that it
//makes sense. Avoided to write it here to keep code short to show
//more of setup in store persisiting
const persistStoreConfigs = {
key: 'root',
storage: myAppStorage,
stateReconciler: autoMergeLevel2
};
const persistantReducer = persistReducer(persistStoreConfigs, rootReducer);
export const store = createStore(persistantReducer);
export const persistor = persistStore(store);
Now passing the store to the App level
import React from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/lib/integration/react';
// This are coming from the store code above that we made
import { persistor, store } from './store';
// This are basically your Custom Componentd
import { HomePage, LoadingView } from './components';
const App = () => {
return (
<Provider store={store}>
// the loading and persistor props are both required!
// Noting that the LoadingView is a custom component
// But the persistor isn't
//The main aim of this two props is to delay the rendering of your app UI until the persited state is retrieved hence the loading screen component
<PersistGate loading={<LoadingView />} persistor={persistor}>
<HomePage />
</PersistGate>
</Provider>
);
};
export default App;
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
Is there any way to create an action in your MobX store, which pushes your app to a new url using react router v4, e.g. this.props.history.push...
I constantly get a history undefined error, but am unsure how to access the history from my store.
The history push called from the component itself does work though..
many thanks! (this is driving me crazy..)
Since I stumbled across the same issue, I'll share my solution. I just put the RouterStore into its own file in my stores directory, then if I needed access to history or location or whatever, I would import the routing store into the store I was currently working in.
./stores/routing.ts
import { RouterStore } from 'mobx-react-router'
export default new RouterStore()
./stores/other-store.ts
import routing from './routing'
export class OtherStore {
#action
doSomething = () => {
routing.push('/new-route')
}
}
export default new OtherStore()
./index.ts
import { Router } from 'react-router-dom'
import { Provider } from 'mobx-react'
import createBrowserHistory from 'history/createBrowserHistory'
import { syncHistoryWithStore } from 'mobx-react-router'
import otherStore from './stores/other-store'
import routing from './stores/routing'
const browserHistory = createBrowserHistory()
const stores = {
otherStore,
routing,
}
const history = syncHistoryWithStore(browserHistory, routing)
ReactDOM.render(
<Provider {...stores}>
<Router history={history}>
<App />
</Router>
</Provider>,
document.getElementById('root'),
)
You can use mobx-react-router to put react-router in a mobx store and then use it by injecting it in components.
You can also pass the router store as a constructor argument to your other stores that need it. This way you have the router history instance available in your mobx store.
I would like to add a simpler solution that does not require any additional libraries. React Router version is 5.2
Among my stores i've created a HistoryStore.js with the following code:
import { createBrowserHistory } from 'history';
export class HistoryStore {
history = createBrowserHistory();
}
Then I create an instance of it in my contexts.js file but you could do it right away.
export const history = new HistoryStore();
After that you import it in your index.js and pass it as a history prop to the Router.
That's it. Now you could import this store into any other and use it there. When you use useHistory hook in your component it gets this history object, so your history in synchronized.