React Redux Saga - Working with multi-saga - reactjs

I'm trying to implement multiply saga, but for some reason it's stopped working to me, and i don't know why.
Here is my full code:
// store/sagas/sagas/auth.js
import { delay } from 'redux-saga';
import { put, call } from 'redux-saga/effects';
// When the client enter input on email / password textboxes on auth form.
export function* sagaFunction1(action) {
yield call(actions.SomeAction1, { 'testSeting' );
}
// store/sagas/watchers/auth.js
import { takeEvery, all } from 'redux-saga/effects';
import * as actionTypes from '../../actions/actionTypes';
import * as sagas from '../sagas/auth';
export function* watchAuthSaga() {
yield all([
takeEvery(actionTypes.SAGA_FUNCTION1, sagas.sagaFunction1)
}
// store/sagas/rootSaga.js
import { all, fork } from 'redux-saga/effects';
import * as watchers from './rootWatchers';
const sagasList = [
...watchers
];
export default function* rootSaga() {
yield all(sagasList.map(saga => fork(saga)));
}
// store/sagas/rootWatchers.js
import { watchAuthSaga } from './watchers/auth';
export default [watchAuthSaga];
// index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
import { BrowserRouter } from 'react-router-dom';
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
import { Provider } from 'react-redux';
import createSagaMiddleware from 'redux-saga';
import * as reducers from './store/reducers/reducers';
import rootSaga from './store/sagas/rootSaga';
import { getEnhancers } from './utils/coreUtils';
import App from './containers/App/App';
import registerServiceWorker from './registerServiceWorker';
// For redux development tools
const composeEnhancers = getEnhancers(compose);
const rootReducer = combineReducers({
auth: reducers.authReducer
});
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, composeEnhancers(applyMiddleware(sagaMiddleware)));
sagaMiddleware.run(rootSaga);
const app = (
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
ReactDOM.render(app, document.getElementById('root'));
registerServiceWorker();
What am i doing wrong?

// store/sagas/rootSaga.js
import * as watchers from './rootWatchers';
const sagasList = [
...watchers ];
Should be import watchers from './rootWatchers', because you are using export default

Related

how can i resolve this error? when actiong emulator .(attempt to invoke virtual method on a null object reference)

I'm using react-native with redux-saga but this error happens when emulator acting
error: attempt to invoke virtual method on a null object reference
i think this code is problem
(App.js)
import React from 'react';
import Store from './store/configureStore'
import {Provider} from 'react-redux';
import {App} from './src/index';
const Root = () => {
return (
<Provider store={Store()}>
<App />
</Provider>
);
};
export default Root;
(configure/configure.js)
import { applyMiddleware, createStore, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { composeWithDevTools } from 'redux-devtools-extension';
import reducer from '../reducers';
import rootSaga from '../sagas';
const Store = () => {
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const enhancer = process.env.NODE_ENV === 'production'
? compose(applyMiddleware(...middlewares))
: composeWithDevTools(
applyMiddleware(...middlewares),
);
const store = createStore(reducer, enhancer);
store.sagaTask = sagaMiddleware.run(rootSaga);
return store;
};
export default Store;
i think error occure is beacuse redux-saga stroe.. how can i fix my code?

"export 'createStore' was not found in 'redux'

WARNING in ./node_modules/#redux-saga/core/dist/redux-saga-core.esm.js 1343:21-28
"export 'compose' was not found in 'redux'
# ./node_modules/redux-saga/dist/redux-saga-core-npm-proxy.esm.js
# ./src/store.js
# ./src/App.js
# ./src/index.js
WARNING in ./src/store.js 6:21-32
"export 'createStore' was not found in 'redux'
# ./src/App.js
# ./src/index.js
I'm facing the problem of creating a redux store. Here, I've added the sample code. If I remove the provider from App.js, it's working fine. Can anyone please help me to resolve this issue?
App.js
import React from 'react';
import Layout from './components/Layout';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { store } from './store'
const App = () => {
return (
<Provider store={store}>
<BrowserRouter>
<Layout/>
</BrowserRouter>
</Provider>
);
}
export default App;
store.js
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import reducers from './redux';
import sagas from './sagas';
const sagaMiddleware = createSagaMiddleware()
export const store = createStore(
reducers,
applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(sagas)
reducer
import { combineReducers } from 'redux';
import { reducer as auth } from './AuthRedux'
const reducers = combineReducers({
auth
});
export default reducers;
sagas
import { takeLatest, all } from 'redux-saga/effects';
import api from '../middleware/api';
import { AuthTypes } from '../redux/AuthRedux'
import { signupSaga } from './AuthSaga'
export default function * root () {
const sagaIndex = [
yield takeLatest(AuthTypes.SIGNUP, signupSaga, api),
];
yield all(sagaIndex)
}
I guess it has something to do with the redux and how I import stuff, but I'm not sure what's wrong there.😩😩
Thanks
In the store.js replace
export const store = createStore(
reducers,
applyMiddleware(sagaMiddleware)
)
with
export const store = createStore(
reducers,
{},
applyMiddleware(sagaMiddleware)
)
Just an arrow in the dark coz it worked for me maybe it should work for you

React- How to make states persists after page refresh?

I made a single page application using React.js with a login page and perfil page. All works well but recently I noticed when refresh my page, all states are empty. Please someone can say me how to fix that issue, I mean what library import and where add it
my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App.jsx';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
serviceWorker.unregister();
this is my App.jsx
import React from 'react';
import '../App.css';
import AppRoutes from './AppRoutes';
import { Provider } from "react-redux";
import store from '../redux/store'
store.dispatch(getTallerList())
const App = () => (
<Provider store={store}>
<AppRoutes />
</Provider> )
export default App;
and my store.js
import { applyMiddleware, combineReducers, createStore } from 'redux'
import { ADD_TO_CART, GET_COURSE_LIST, USUARIO_LOGIN } from './action'
import { composeWithDevTools } from 'redux-devtools-extension'
import { persistStore, persistReducer } from 'redux-persist'
import thunk from 'redux-thunk'
const initialCart = {
cart:[]
}
const initialCourses ={
courses:[]
}
const initialUser ={
user:{}
}
const cartReducer = ( state = initialCart,action) => {
if(action.type===ADD_TO_CART)
{
if(state.cart.find(c=>c===action.id))
{
return state
}
return{
...state,
cart: state.cart.concat(action.id),
}
}
return state
}
const coursesReducer = (state=initialCourses, action) =>{
console.log(action)
if(action.type === GET_COURSE_LIST){
return {
...state,
courses: action.courses
}
}
return state
}
const userReducer = (state=initialUser, action)=>{
console.log(action)
if(action.type === USER_LOGIN){
return {
...state,
user: action.user
}
}
return state
}
export default createStore(combineReducers({cartReducer, coursesReducer, userReducer}), composeWithDevTools(applyMiddleware(thunk)))
Try to store value in local storage and at the time of page load get value from local storage. If you have some more values you should use redux for data storage.
It's not an issue, it's the way it works. When you refresh the entire app builds once again from the scratch.
But to persist the store upon refresh you can use these redux middlewares -
redux-persist or
redux-storage
Use this configuration as you are using redux-persist. This is my configuration, just change the main app, reducers, and actions according to your need.
import React from 'react';
import ReactDOM from 'react-dom';
import MyApp from './MyApp';
import {Provider} from 'react-redux';
import {applyMiddleware, createStore} from "redux";
import allReducers from './reducers/index';
import {persistReducer, persistStore} from 'redux-persist';
import {PersistGate} from 'redux-persist/integration/react';
import storage from 'redux-persist/lib/storage';
import thunk from "redux-thunk";
const persistConfig = {
key: 'root',
storage,
};
const persistedReducer = persistReducer(persistConfig, allReducers);
let store = createStore(persistedReducer, applyMiddleware(thunk));
let persistor = persistStore(store);
ReactDOM.render(<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<MyApp/>
</PersistGate>
</Provider>, document.getElementById('root'));
Updated : you can do like this
import {combineReducers} from "redux";
import Users from './load-user';
const allReducers = combineReducers({
users: Users,
})
export default allReducers

Why "State" is empty after action is dispatched?

I am working on Log in authentication. After user logged in successfully I want to show log out button based on token value in the state. User gets logged in successfully But actually state is empty and have no values which are passed from express server. So if state token property is empty it does not show log out button after logged in .
api code
import axios from 'axios'
export default {
user:{
login:(credential) => axios.post('/api/auth',{credential}).then(res => res.data.user)
}
}
action code
import {USER_LOGGED_IN} from '../types'
import api from '../api'
export const userLoggedIn = user => ({
type: USER_LOGGED_IN,
user
});
export const login = (credential) =>(dispatch) => api.user.login(credential).then(user => dispatch(userLoggedIn(user)))
type code
export const USER_LOGGED_IN = 'USER_LOGGED_IN'
user reducer
import { USER_LOGGED_IN } from "../types";
export default function user(state ={}, action = {}) {
switch (action.type) {
case USER_LOGGED_IN:
return action.user;
default:
return state;
}
}
rootReducer
import { combineReducers } from "redux";
import user from "./reducers/user";
// import books from "./reducers/books";
export default combineReducers({
user:()=>({
})
});
HomePage
import React from 'react'
import {connect} from 'react-redux'
import PropTypes from 'prop-types'
import { Link } from 'react-router-dom'
function HomePage({isAuthenticated}) {
return (
<div>
<h1>Home Page</h1>
{ isAuthenticated ? <button>Logout</button> : <Link to ="/login">Login</Link>}
</div>
)
}
HomePage.propTypes ={
isAuthenticated:PropTypes.bool.isRequired
}
function mapStateToProps(state){
console.log(state.user.token); // this shows undefined
return{
isAuthenticated:!!state.user.token
}
}
export default connect(mapStateToProps)(HomePage)
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom'
import 'semantic-ui-css/semantic.min.css'
import {createStore,applyMiddleware} from 'redux'
import {Provider} from 'react-redux'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'
import App from './App';
import * as serviceWorker from './serviceWorker';
import rootReducer from './rootReducer'
const store = createStore(rootReducer,composeWithDevTools(applyMiddleware(thunk)))
ReactDOM.render(<BrowserRouter><Provider store={store}><App /></Provider></BrowserRouter>, document.getElementById('root'));
serviceWorker.unregister();
update rootreduer file to
import { combineReducers } from "redux";
import user from "./reducers/user";
// import books from "./reducers/books";
export default combineReducers({
user
});
Actually you are not providing your user reducer in combine reducers, you can do as
import { combineReducers } from "redux";
import user from "./reducers/user";
export default combineReducers({
user
})
});
Hope it helps

React-router-redux push action is not working

I am trying to navigate to Main page once authentication is successful, I am using redux-saga for making API calls. Below is my login generator function:
import * as Type from '../actions/types';
import { takeLatest, put, call } from 'redux-saga/effects';
import firebase from 'firebase';
import { push } from 'react-router-redux';
function* loginUser(action) {
const auth = firebase.auth();
try{
console.log(action.user);
const result = yield call([auth, auth.signInWithEmailAndPassword], action.user.email, action.user.password);
console.log('login sucess');
yield put({type: Type.AUTH_SUCCESSFULL, user: action.user, authMessage:'Login Success'});
console.log('done'); //being logged
yield put(push('/home')); /not being redirected to home. Even the browser url is not changing
console.log('pushed'); //being logged
}
catch(error){
console.log(error.message);
yield put({type: Type.AUTH_FAILED, errorMessage: error.message});
}
}
I just installed react-router-redux and tried doing this, Can someone please tell me what I am doing wrong?
I faced the same issue and following is my solution. Code you have added has not an issue. You need do some extra works to make this work.
Reducer.js
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import { History } from 'history'
const redusers = {
...
}
const mainReducer = (history: History) => combineReducers({
router: connectRouter(history),
...redusers
})
export default mainReducer;
Store.js
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import logger from 'redux-logger';
import { createBrowserHistory } from 'history'
import { routerMiddleware } from 'connected-react-router'
import mainReducer from './mainReducer';
import rootSaga from './rootSaga';
export const history = createBrowserHistory()
const configureStore = (preloadedState?: any) => {
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
mainReducer(history),
preloadedState,
applyMiddleware(routerMiddleware(history), logger, sagaMiddleware),
);
sagaMiddleware.run(rootSaga);
return store;
};
export default configureStore;
index.js
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import * as serviceWorker from './serviceWorker';
import configureStore, { history } from './store';
const store = configureStore();
const app = (
<Provider store={store}>
<App history={history} />
</Provider>
);
App.js - only added necessary code lines bellow
...
import { History } from 'history'
import { ConnectedRouter } from 'connected-react-router'
...
const {history} = props;
...
return(){
...
<ConnectedRouter history={history}>
{routes}
</ConnectedRouter>
...
}
After setting up above things on your app, it will work as you want.
The other thing is we are no longer using BrowserHistory in the app because custom history has implemented.

Resources