I would like to know if this is just a normal behaviour with redux persist or if there's something wrong with my code.
Whenever I update my redux state, it gets updated in redux persist as I console.log() it.
But whenever I delete the app and re install it back, I get an older version of the state i.e the not updated one.
Is redux persist stored on the app or sth?
This is how I set my redux persist:
const persistConfig = {
key: 'root',
storage:AsyncStorage,
}
const rootReducers = combineReducers({
login:AuthReducer,
location: LocationReducer,
})
const persistedReducer = persistReducer(persistConfig, rootReducers)
const AllReducers = createStore(persistedReducer,applyMiddleware(ReduxThunk))
let persistor = persistStore(AllReducers)
I see no problem with what I setup as it works fine with my other apps.
<Provider store={AllReducers}>
<PersistGate loading={null} persistor={persistor}>
{....}
</PersistGate>
</Provider>
Also, I am using expo development build. I recently just prebuilt the app and deleted the former one to reinstall the newer version and that's when I found out about this problem.
I would wish that if the state isn't the newer version the user should get logged out. Infact, I do not understand why after deleting an app, the redux state still persist till then.
My question is: Is this the correct behaviour of redux persist? Also, I would wish for the redux persist storage to be deleted after uninstall. How do I go about that?
Related
I use 99% on my screens fetch. So if the connection is lost and data are not fetched my screen is empty. So when the internet is again online nothing happens.
So then I downloaded netInfo but if I disable my internet connection then my isOffline state is always false. Nothing happens, how can I detect on real time when internet is off/on?
const [isOffline, setIsOffline] = useState(false);
useEffect(() => {
const removeNetInfoSubscription = NetInfo.addEventListener((state: NetInfoState) => {
const offline = !(state.isConnected && state.isInternetReachable)
console.log(offline)
setIsOffline(offline)
})
return () => removeNetInfoSubscription()
}, [])
console.log(isOffline);
If you are using an old version of React Native, you might face this issue with netinfo. Downgrading the version of netinfo to v6 (or updating the React Native to version>=0.65) might make it work.
See this GitHub issue
I have a react native app and whenever I try to login or logout the app crashes .. I am not getting any error logs in React Native Debugger.
so the App Crashes and then when I reopen the app the changes have already taken effect ( i.e :- If I was trying to login I would be logged in when I reopen the app)
I have 2 files for Navigation
CofficNavigator.tsx
// This file has all the routing
// here BottomNavigator is a tab Navigator and AuthNavigator is a stack navigator
// Before the app crashing all the correct state is set but it just crashes
// ----------- Final Stack Navigator ----------------
const FinalStackNavigator = createStackNavigator();
export const FinalNavigator = (props: any) => {
const authContext = useContext(AuthContext);
const [signedIn, setSignedIn] = useState<boolean | null>(
authContext.isLoggedIn
);
useEffect(() => {
if (authContext.isLoggedIn !== signedIn && !authContext.isLoading) {
setSignedIn(authContext.isLoggedIn);
}
}, [authContext]);
return (
<FinalStackNavigator.Navigator>
{signedIn ? (
<>
<FinalStackNavigator.Screen
name="BottomNavigator"
component={BottomNavigator}
options={{ headerShown: false }}
/>
</>
) : (
<>
<FinalStackNavigator.Screen
name="AuthNavigator"
component={AuthNavigator}
/>
</>
)}
</FinalStackNavigator.Navigator>
);
};
AppNavigator.tsx
export const AppNavigator = (props: any) => {
return (
<NavigationContainer>
<FinalNavigator />
</NavigationContainer>
);
};
-------- Login Logic flow -------------
on success of login API I call this line
await authContext.changeCofficToken(result.data.login.token);
AuthContext.ts
const changeCofficToken = async (token: string) => {
await setItem("cofficToken", token);
setIsLoggedIn(true);
setCofficToken(token);
};
helper.ts
export const setItem = async (key: string, value: any) => {
await AsyncStorage.setItem(key, value);
};
App.tsx
return (
<AuthContextProvider>
<FilterContextProvider>
<SearchTermContextProvider>
<ShowVerticalListContextProvider>
<CouponContextProvider>
<ApolloProvider client={client}>
<AppNavigator />
</ApolloProvider>
</CouponContextProvider>
</ShowVerticalListContextProvider>
</SearchTermContextProvider>
</FilterContextProvider>
</AuthContextProvider>
);
------ End of Login Logic code flow -------
Error logs from my IOS Simulator
com.apple.CoreSimulator.SimDevice.957FA264-501C-44C3-80F3-9E8D1F600A1E[15500] (UIKitApplication:host.exp.Exponent[e036][rb-legacy][15601]): Service exited due to SIGABRT
assertion failed: 19F101 17F61: libxpc.dylib + 83746 [ED46009E-B942-37CC-95D4-82CF3FE90BD8]: 0x7d
Please Note :- I am using Expo if it matters
Video Link :- https://fisico-dhaval.s3.ap-south-1.amazonaws.com/Screen+Recording+2020-08-20+at+5.38.06+PM.mov
If you need any other code snippets then please do lemme know
Any help will be appreciated
Can you share the code where you setSignin. In case if you are saving and clearing token, make sure those libraries are supported and linked properly.
Service exited due to SIGABRT is a common issue in Native iOS development, it can be cause due to various events. While working on react-native, I have never experienced this error. But I'm adding some of my observation, may be that can help you,
This can be cause due to some buggy component, which are not compatible with Expo version. So, you need to add many console.log or may be comment some things and check is there any functionality or a component causing this error. A buggy component can be a culprit.
If you have pod installed, Make sure you check all your libraries.You likely have some issue with an installed external library. and make sure you run pod install and delete node_modules folder and then run npm install again (close the packager too)
You can also use sentry or any other crash reporting library to detect crashes, It will give you the exact line number.
Sometimes the crash reporting libraries won't work, the reason can be that the crash occurs before the js bundle is loaded and because of that, the library is not yet initialised and it can't detect the crash. If so you can install a native crash reporting library, You can use fabric for that, or even bugsnag.
These are few scenarios, I've observed via which you can debug or detect what's the real cause of this error.
I have two react native components, One is profile(showing logged user details) and another one for login.
In login component I set the user details to AsyncStorage.
import {AsyncStorage} from 'react-native';
Adding user to AsyncStorage:
const user = {
fname:"Tenusha",
lname:"Guruge"
}
AsyncStorage.setItem("user",JSON.stringify(user))
In the profile component I read the AsyncStorage
componentDidMount() {
AsyncStorage.getItem("user").then(user => {
console.log(user)
this.setState({user})
})
}
When logout I clear the AsyncStorage:
AsyncStorage.removeItem("user")
Problem is Once I log in and set the user details to AsyncStorage, it store the data and I can view them in profile component. Once user logout, the data in storage are cleared, but when I navigate to profile component the previously loaded data is still there.
I need a way to read the current AsyncStorage data when every time user navigate to profile component.
To be sure a component is unmounted you can use createSwitchNavigator.
You can use a loginScreen as child while the other child is your Drawer.
When doing a logout you clear your asyncStorage and then navigate to the loginScreen and the SwitchNavigator will unmount your Drawer.
DrawerNavigation will keep the screens active while moving between his childs after every screens's first focus, making every componentDidMount getting triggered only at first render.
Track navigation changes and clear state here
Consider state-manager like redux it will be cleanest approach
Your issue is that your state is not getting cleared when using DrawerNavigator instead you can use stackNavigator if you want your component to unmount when navigating out and clearing the state automatically.
Another approach can be of using state management library such as redux or flux and clear out state whenever user is logging out.
I'm using the Contentful CMS JS SDK and the code below does not update my React Hook state. It's more of a promises combined with react hooks combined with React render issue - I believe. I understand that the promise sets the hook value when it is resolved at a later time, but by that time my component already rendered with the initial data (empty string), so if this is the case, how can I make my component re-render when the react hook state is set with the correct value from the promise, so that my Button displays it.
Any help appreciated. Thanks
Problem lies within here.
...
import client from 'contentful'
const [name, setName] = useState('')
client.getEntry(data.fields.store.sys.id)
.then(entry => setName(entry.fields.name))
.catch(console.error)
console.log('STORE URL', name) // name is not set
...
<Button title={name} /> // name still not set
....
I just tried your code and it seems to work for me. :)
https://codesandbox.io/embed/react-hooks-demo-e4wgo
I think you should use useEffect though as described in this article.
Using React-Native (0.19) and Redux, I'm able to navigate from scene to scene in React Components like so:
this.props.navigator.push({
title: "Registrations",
component: RegistrationContainer
});
Additionally I'd like to be able push components to the navigator from anywhere in the app (reducers and/or actions).
Example Flow:
User fills out form and presses Submit
We dispatch the form data to an action
The action sets state that it has started to send data across the wire
The action fetches the data
When complete, action dispatches that the submission has ended
Action navigates to the new data recently created
Problems I'm seeing with my approach:
The navigator is in the props, not the state. In the reducer, I do not have access to the props
I need to pass navigator into any action that needs it.
I feel like I'm missing something slightly simple on how to access Navigator from actions without sending in as a parameter.
In my opinion the best way to handle the navigation with Redux is with react-native-router-flux, because it can delegate all the navigation logic to Redux:
You can change the route from the reducer;
You can connect the router to the store and dispatch its own actions that will inform the store about route changes (BEFORE_ROUTE, AFTER_ROUTE, AFTER_POP, BEFORE_POP, AFTER_DISMISS, BEFORE_DISMISS);
An example
Here is an example on how easily you can save the currently focused route in the store and handle it in a component (that will be aware of being focused):
1. Connect a <Route> to Redux
Connecting a <Route> to Redux is easy, instead of:
<Route name="register" component={RegisterScreen} title="Register" />
you might write:
<Route name="register" component={connect(selectFnForRegister)(RegisterScreen)} title="Register" />
You can also simply connect the component itself in its own file like you usually do.
2. Connect a <Router> to Redux
If you need to inform Redux of the navigation status (i.e. when you pop a route) just override the <Router> component included in react-native-router-flux with a connected one:
import ReactNativeRouter, { Actions, Router } from 'react-native-router-flux'
const Router = connect()(ReactNativeRouter.Router)
Now when you use a <Router> it will be connected to the store and will trigger the following actions:
Actions.BEFORE_ROUTE
Actions.AFTER_ROUTE
Actions.AFTER_POP
Actions.BEFORE_POP
Actions.AFTER_DISMISS
Actions.BEFORE_DISMISS
Take a look at this for an example.
3. Catch the interested actions in your reducer
For this example I have a global reducer (where I keep the information needed by all my app) where I set the currentRoute:
case Actions.AFTER_ROUTE:
case Actions.AFTER_POP:
return state.set('currentRoute', action.name)
Now the reducer will catch every route change and update global.currentRoute with the currently focused route.
You also can do many other interesting things from here, like saving an history of the navigation itself in an array!
4. Update your component on focus
I'm doing it on componentDidUpdate of my component of the route named payment.
If global.currentRoute is payment and the previous global.currentRoute was different, than the component has just been focused.
componentDidUpdate(prevProps) {
const prevRoute = prevProps.global.currentRoute
const currentRoute = this.props.global.currentRoute
if (currentRoute === 'payment' && prevRoute !== currentRoute) {
this.props.actions.doSomething()
}
}
P.S.: Remember to check currentRoute === 'payment', otherwise you'll start doSomething() on every route change!
Also, take a look a the README.md for learning other stuff about the integration with Redux.
Hope it helps, long live Redux!
Maybe you could pass the information about title and component in an action and the component with the navigator can then push the right scene with the information of the state.