My Expo React Native project is continuously crashing on real device after building.
I used redux saga and its other dependencies for state management and for api call. I used documentation for to learn about. I dont have much knowledge about it.
App.js file
import { SafeAreaView } from "react-native";
import { NativeBaseProvider } from "native-base";
import { InsideStack } from "./src/stackNavigator";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { store, persistor } from "./src/store";
const config = {
strictMode: "warn",
};
function App() {
return (
<SafeAreaView style={{ flex: 1 }}>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<NativeBaseProvider config={config}>
<InsideStack />
</NativeBaseProvider>
</PersistGate>
</Provider>
</SafeAreaView>
);
}
export default App;
Redux index file
import { applyMiddleware } from "redux";
import { legacy_createStore as createStore } from "redux";
import createSagaMiddleware from "redux-saga";
import { persistStore, persistReducer } from "redux-persist";
import AsyncStorage from "#react-native-async-storage/async-storage";
import rootSagas from "./RootSagas";
import { rootReducer } from "./RootReducer";
const sagaMiddleware = createSagaMiddleware();
const persistConfig = {
key: "root",
storage: AsyncStorage,
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = createStore(persistedReducer, applyMiddleware(sagaMiddleware));
let persistor = persistStore(store);
sagaMiddleware.run(rootSagas);
export { store, persistor };
root reducer
import { combineReducers } from "#reduxjs/toolkit";
import MainReducer from "../screens/redux/reducers";
export const rootReducer = combineReducers({
mainreducer: MainReducer,
});
Root saga
import { takeEvery, all, fork, SelectEffect, select } from "redux-saga/effects";
import MainSagas from "../screens/redux/saga";
function* watchAndLog() {
yield takeEvery("*", function* logger(action) {
const state = yield select();
console.debug("action", action);
console.debug("state after", state);
});
}
export default function* root() {
console.log(process.env.NODE_ENV);
const allForks = [fork(MainSagas)];
if (process.env.NODE_ENV === "development") {
allForks.unshift(fork(watchAndLog));
}
yield all(allForks);
}
Related
I was trying out react redux, but each time I add redux logic in my App component, I don't get any output on the browser window.
I have three files:
App.js
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { increment } from './counterSlice';
function App() {
const count = useSelector((state) => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<h1>Values is {count}</h1>
<button onClick={() => dispatch(increment)}>Plus</button>
</div>
);
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
counterSlice.js
import { createSlice } from "#reduxjs/toolkit";
const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0
},
reducers: {
increment: state => {
state.value++;
},
decrement: state => {
state.value--;
}
}
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer
And finally the store.js
import { configureStore } from "#reduxjs/toolkit";
import counterReducer from "./counterSlice";
const store = configureStore({
reducer: counterReducer
})
export default store;
What could be the problem?
I tried to run the code using npm start and was expecting to see the initial state value stored in the counter slice display in the browser window.
i want to cnnect redux-saga witdh react-native but this error keep happen...
TypeError: store.getState is not a function. (In 'store.getState()',
'store.getState' is undefined
Warning: Failed prop type: Invalid prop store of type function
supplied to Provider, expected object
this is my code
(index.js)
import {AppRegistry} from 'react-native';
import Root from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => Root);
(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;
(src/index.js)
import React from 'react';
import Navigator from './Screens/Navigator';
import styled from 'styled-components/native';
const App = ({}) => {
return (
<Navigator/>
);
};
export {App};
(store/cofigurestore.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;
(reducer/index.js)
import { combineReducers } from 'redux';
import user from './user';
import post from './post';
// (이전상태, 액션) => 다음상태
const rootReducer = (state, action) => {
switch (action.type) {
// case HYDRATE:
// // console.log('HYDRATE', action);
// return action.payload;
default: {
const combinedReducer = combineReducers({
user,
post,
});
return combinedReducer(state, action);
}
}
};
export default rootReducer;
(sage/index.js)
import { all, fork } from 'redux-saga/effects';
import axios from 'axios';
import postSaga from './post';
import userSaga from './user';
export default function* rootSaga() {
yield all([
fork(postSaga),
fork(userSaga),
]);
}
please help me ......... i want to resolve this problem...... but i don't know how can i do that
In you App.js you should be passing the result of calling you Store function to the Provider and not the function itself.
const Root = () => {
return (
<Provider store={Store()}>
<App />
</Provider>
);
};
I'm tranfer reactjs project to nextjs with react-redux, redux, nexti18next, next-redux-wrapper here is _app.js and redux.js it run right but if i add withRedux it is error. Please tell me how to resolve this problem or advide me some solution!
import React from "react";
import App, { Container } from "next/app";
import { appWithTranslation } from "../i18n";
import ScrollToTop from "../components/ScrollToTop";
import { createBrowserHistory } from "history";
import { Provider } from "react-redux";
import storeConfig from "../redux";
import compose from "recompose/compose";
const history = createBrowserHistory();
const store = storeConfig();
import withRedux from "next-redux-wrapper";
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
}
render() {
const { Component, pageProps } = this.props;
console.log(store)
return (
<Container>
<ScrollToTop>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</ScrollToTop>
</Container>
);
}
}
export default compose(appWithTranslation)(MyApp);
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import getQuote, { initGetQuoteState } from './Modules/GetQuote';
import getSlider, { initGetSliderState } from './Modules/GetSlider';
import getUser, {initGetUserState } from './Modules/User';
import {composeWithDevTools } from 'redux-devtools-extension'
const initState = {
getQuote: initGetQuoteState,
getSlider: initGetSliderState,
getUser: initGetUserState
};
const rooteReducer = combineReducers({
getQuote,
getSlider,
getUser
});
const store = () => createStore(rooteReducer, initState, composeWithDevTools(applyMiddleware(thunk)))
export default store;
Here is example of NextJS/Typescript/Redux/Styled-Components/next-i18next app sample.
// _app.tsx
import * as React from "react";
import App, { AppInitialProps, AppContext } from "next/app";
import withRedux from "next-redux-wrapper";
import { Provider } from "react-redux";
import { ThemeProvider } from "styled-components";
import { theme } from "#Definitions/Styled";
import { appWithTranslation } from "#Server/i18n";
import { AppWithStore } from "#Interfaces";
import { makeStore } from "#Redux";
import "#Static/css/main.scss";
class ProgressiveWebApp extends App<AppWithStore> {
static async getInitialProps({
Component,
ctx,
}: AppContext): Promise<AppInitialProps> {
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
return { pageProps };
}
render() {
const { Component, pageProps, store } = this.props;
return (
<Provider store={store}>
<ThemeProvider theme={theme}>
<Component {...pageProps} />
</ThemeProvider>
</Provider>
);
}
}
export default withRedux(makeStore)(appWithTranslation(ProgressiveWebApp));
//i18.ts
import NextI18Next from "next-i18next";
const NextI18NextInstance = new NextI18Next({
defaultLanguage: "en",
otherLanguages: ["es"],
});
export const {
appWithTranslation,
withTranslation,
useTranslation,
i18n,
} = NextI18NextInstance;
export default NextI18NextInstance;
and I have path alias in tsconfig
"paths": {
"#Definitions/*": ["definitions/*"],
"#Interfaces": ["interfaces"],
"#Redux": ["redux-store"],
"#Server/*": ["server/*"]
}
hope this helps somebody!
I am learning redux and wanted to know how can I save the state locally so when I refresh after making some changes to state it remains. I came to know about redux-persist and saw the github doc describing how to use it but its not very clear to me.
Here is the index.js code of my app -
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import App from './components/app';
import reducers from './reducers';
const createStoreWithMiddleware = applyMiddleware()(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<App />
</Provider>
, document.querySelector('#container'));
How can I achieve it ?
//In your createStore have this code
import { applyMiddleware, compose, createStore } from 'redux'
import thunkMiddleware from 'redux-thunk';
import { createLogger } from 'redux-logger';
import rootReducer from '../reducers';
import { persistReducer } from 'redux-persist'
import localForage from 'localforage';
const loggerMiddleware = createLogger();
export default (initialState = {}) => {
// ======================================================
// Middleware Configuration
// ======================================================
const middleware = [thunkMiddleware, loggerMiddleware]
// ======================================================
// Store Enhancers
// ======================================================
const enhancers = []
const __DEV__ = process.env.NODE_ENV !== 'production';
if (__DEV__) {
const devToolsExtension = window.devToolsExtension
if (typeof devToolsExtension === 'function') {
enhancers.push(devToolsExtension())
}
}
// ======================================================
// Store Instantiation and HMR Setup
// ======================================================
let config = {
key: 'root',
storage: localForage,
whitelist: ['user'],
debug: __DEV__
}
let configureReducer = persistReducer(config, rootReducer)
const store = createStore(
configureReducer,
initialState,
compose(
applyMiddleware(...middleware),
...enhancers
),
)
return store
}
// In your App.js or root app, do this in your componentDidMount
persistStore(
store,
undefined,
() => {
console.log('callback::')
}
)
Here is what you should do for creating your store, using redux-persist in store.js:
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import { persistStore, autoRehydrate } from 'redux-persist';
import localForage from 'localforage';
import { routerReducer } from 'react-router-redux';
import reducers from './container/reducers';
import middlewares from './middlewares';
const reducer = combineReducers({
...reducers,
routing: routerReducer,
});
export const initStore = (state) => {
const store = createStore(
reducer,
{},
compose(
applyMiddleware(...middlewares),
autoRehydrate(),
),
);
persistStore(store, {
storage: localForage,
whitelist: ['login'],
});
return store;
};
In your app.js, create your store this way:
import React from 'react';
import { Provider } from 'react-redux';
import { browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import createRoutes from './routes'; // Contains the routes
import { initStore, persistReduxStore } from './store';
import { appExample } from './container/reducers';
const store = initStore(appExample);
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { rehydrated: false };
}
componentWillMount() {
persistReduxStore(store)(() => this.setState({ rehydrated: true }));
}
render() {
const history = syncHistoryWithStore(browserHistory, store);
return (
<Provider store={store}>
{createRoutes(history)}
</Provider>
);
}
}
I create a React Native app. My index.ios.js where I add middlewares to the store.
import React, { Component } from 'react'
import {
AppRegistry,
} from 'react-native'
import { Provider } from 'react-redux'
import { applyMiddleware, createStore } from 'redux'
import createLogger from 'redux-logger'
import createSagaMiddleware from 'redux-saga'
import reducer from './src/reducers'
import * as sagas from './src/sagas'
import Scene from './src/components/scene'
const store = createStore(
reducer,
applyMiddleware(createSagaMiddleware(...sagas), createLogger())
);
const CitiesApp = () => (
<Provider store={store}>
<Scene />
</Provider>
);
AppRegistry.registerComponent('CitiesApp', () => CitiesApp);
I have an action:
export const USER_FETCH_REQUESTED = 'USER_FETCH_REQUESTED';
export const fetchUser = () => ({
type: USER_FETCH_REQUESTED
});
Which I call from componentDidMount in a component
componentDidMount() {
this.props.dispatch(fetchUser());
console.log('componentDidMount')
}
Also I have a saga:
export function* watchUserFetch() {
console.log('watchUserFetch');
yield take(actions.USER_FETCH_REQUESTED);
yield fork(fetchUser);
}
function* fetchUser() {
try {
const user = yield call(() => Api.fetchUser());
yield put({type: actions.USER_FETCH_SUCCEEDED, user});
} catch (e) {
yield put({type: actions.USER_FETCH_FAILED, message: e.message});
}
}
But the saga doesn't work. I don't saw watchUserFetch in console and fetchUser function doesn't run.
Where is my mistake? Why fetchUser doesn't run?
create root saga
export default function* rootSaga() {
yield [
watchUserFetch()
]
}
then run rootSaga
import createSagaMiddleware from 'redux-saga';
import rootSaga from './sagas.js';
const sagaMiddle= createSagaMiddleware();
const store = createStore(reducer,
applyMiddleware(sagaMiddle,createLogger())
);
sagaMiddle.run(rootSaga);
webpackbin example