My application make a post request to an api. The issue is that the post request does not work properly.
Now the data from :
const postData = () => {
postMessageNew({
first: 1,
second: 2
});
};
... riches till :
export const postMessageNew = newMessage => {
console.log(newMessage);
return {
type: POST_MESSAGE,
newMessage
};
};
So, the data after clicking button, reaches only till above console.log, not till post request from saga file. What could be the problem? And how to fix the code? Why the values don't appear in the code bellow?
function* postNewMessage(newMessage) {
console.log(newMessage);....
Demo: https://codesandbox.io/s/upbeat-franklin-g8x3o?file=/src/App.js:129-219
You need to set up Redux properly, including a reducer, and use the saga middleware to run your saga:
import React from "react";
import { render } from "react-dom";
import { Provider } from "react-redux";
import { createStore, applyMiddleware } from "redux";
import createSagaMiddleware from "redux-saga";
import rootSaga from "./sagas";
import rootReducer from "./Reducer";
import App from "./App";
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(rootSaga);
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
Check out a working example: https://codesandbox.io/s/happy-khayyam-uy06r?file=/src/App.js
Related
I am using Redux and Redux saga with Nextjs, i wrapped the store on _app.js file and when i call the api with post or get requests Redux-Saga is getting called at least two times, specially for post requests for example if i want to register a user using the api it is registering the user two times on the database
PS: I am using rootSaga and i am not calling a saga twice there
This is my store file:
import { createStore, applyMiddleware, compose } from "redux";
import createSagaMiddleware from "redux-saga";
import reducers from "./reducers";
import sagas from "./sagas";
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
export function configureStore(initialState) {
const store = createStore(
reducers,
initialState,
compose(applyMiddleware(...middlewares))
);
sagaMiddleware.run(sagas);
if (module.hot) {
module.hot.accept("./reducers", () => {
const nextRootReducer = require("./reducers");
store.replaceReducer(nextRootReducer);
});
}
return store;
}
export const wrapper = createWrapper(configureStore, { debug: true });
And this is my _app.js file
import "../styles/styles.global.scss";
import "../styles/Home.module.scss";
import React from "react";
import App, { Container } from "next/app";
import { Provider, connect } from "react-redux";
import withRedux from "next-redux-wrapper";
import { configureStore, wrapper } from "../libs/store";
const context = React.createContext(undefined);
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { ...pageProps };
}
render() {
const { Component, pageProps, router } = this.props;
return (
<Provider store={configureStore()} context={context}>
<Component {...pageProps} key={router.asPath} />
</Provider>
);
}
}
export default wrapper.withRedux(MyApp);
Thank you.
I Fixed it by removing the provider from _app.js and deleting _document.js
PS: This solutions is for Nextjs >= 10.0.0
I am using redux-thunk/ReactJs for async actions and i am getting error like this Error: Actions must be plain objects. Use custom middleware for async actions.
But i have installed redux-thunk and have configured it in index.js file
Here is my index.js file :
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import myReducer from './reducers/index';
const store = createStore(
myReducer,
applyMiddleware(thunk),
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
registerServiceWorker();
and this is my 'action.js' file :
import * as types from './../constants/ActionTypes';
import callApi from '../utils/callApi';
export const actFetchProductsRequest = () => {
return dispatch => {
return callApi('products', 'GET', null).then(res => {
dispatch(actFetchProducts(res.data))
}).catch(err => console.log(err))
}
}
export const actFetchProducts = (products) => {
return {
type: types.LIST_ALL,
products
}
}
What is the problem here , thanks ?
Try this:
export const actFetchProducts = (products) => {
return ({
type: types.LIST_ALL,
products
})
}
You need to put the return object in the parentheses. If you don't, then you'll definitely get this error.
Hopefully, that helps!
I am using Redux-saga, so that I can fetch items from my API side. I have initialized my saga middleware in the index page as per the instruction given in the redux-saga documentation.
The following snippet is my /src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import createSagaMiddleware from 'redux-saga';
import reducer from './reducers';
import App from './root-components/app';
export const sagaMiddleware = createSagaMiddleware()
const store = createStore(reducer, applyMiddleware(sagaMiddleware));
ReactDOM.render(
<Provider store={store}>
<div>
<App />
</div>
</Provider>,
document.getElementById('root')
);
My component is src/component/index.jsx
import React, { Component } from 'react';
import { sagaMiddleWare } from '../index.js';
import { fetchPrescriptionsFromUrl } from '../actions/presAction';
class Index extends Component {
componentWillMount(){
const res = "434566ytui87unhygt99";
sagaMiddleware.run(fetchPrescriptionsFromUrl);
fetchPrescriptionsFromUrl(res);
}
render(){
return(
<div>
<h1> My First Component </h1>
</div>
)
}
}
export default Index;
I am calling action fetchPrescriptionsFromUrl(res) passing the parameter res along with it. My action is presAction is
import {call, put} from "redux-saga/effects";
import axios from 'axios';
const getCharacters = (accessPoint) => {
axios.get(accessPoint)
}
export function *fetchPrescriptionsFromUrl(accessToken){
console.log('AT', accessToken)
try {
const response = yield call(getCharacters(accessToken))
} catch (e) {
console.log(e)
}
}
On console.log of argument which is been passed from the component index.jsx is stated as undefined.
I am beginner in redux-saga, don't know where am making error. It will be helpful if I got any solutions for this problem.
Redux Saga call function cannot be used this way. It should look like this
const response = yield call(getCharacters, accessToken)
In your case getCharacters was evaluated imidiatelly and it's result was passed into call
Also you shouldn't use sagaMiddleWare in your Index component. Point of (not just saga) middleware is that you dispatch actions as normal and then catch concrete actions in your middleware
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.
I've been trying to use redux-perist to save my redux-state to AsyncStorage. Although I keep getting an error:
_this.store.getState is not a function
I'm not sure why this is happening?
Here is my setup:
configureStore.js:
import {AsyncStorage,} from 'react-native';
import { createStore, applyMiddleware, compose, combineReducers, } from 'redux';
import reduxThunkMiddleware from 'redux-thunk';
import Reactotron from 'reactotron';
import * as reducers from './modules';
import devTools from 'remote-redux-devtools';
import {persistStore, autoRehydrate} from 'redux-persist'
Reactotron.connect({
enabled: __DEV__,
});
const enhancer = compose(
autoRehydrate(),
applyMiddleware(
reduxThunkMiddleware,
Reactotron.reduxMiddleware,
),
devTools()
);
export default function configureStore(initialState) {
const store = createStore(
combineReducers({
...reducers,
}),
initialState,
enhancer,
);
Reactotron.addReduxStore(store, {storage: AsyncStorage});
return store;
}
App.js:
Here is where I connect my store, to my <provider>:
import React from 'react';
import {AsyncStorage} from 'react-native';
import { Provider, connect } from 'react-redux';
import { Router } from 'react-native-router-flux';
import routes from '#routes/app';
import createStore from './redux/create'; // Returns store object from the above configureStore.js!
import {persistStore} from 'redux-persist'
const RouterWithRedux = connect()(Router);
const store = persistStore(createStore(), {storage: AsyncStorage}); // Not working??
const Kernel = () => (
<Provider store={store}>
<RouterWithRedux scenes={routes} />
</Provider>
);
export default Kernel;
const RouterWithRedux = connect()(Router);
const store = createStore();
const persistor = persistStore(store, {storage: AsyncStorage}); // Not working??
const Kernel = () => (
<Provider store={store} persistor={persistor}>
<RouterWithRedux scenes={routes} />
</Provider>
);
The problem was I had to pass down a persistor field as well as the store field.
After adding in the persistor field, my store was being persisted into AsyncStorage
EDIT:
This worked at the time - It has occured to me that this not the correct solution to the problem. But I'm still getting responses that it still works, if someone could provide another answer for everyone else, that'd be great.