Access Store on different screens in react-native - react-native

I am using a 'react-native-navigation' module for navigation in my app. I have declared my screens as below
import Screen1 from '../container/Screen1';
import Screen2 from '../container/Screen2';
const store = myStore();
Navigation.registerComponent('Screen1',() => Screen1,store,Provider);
Navigation.registerComponent('Screen2',() => Screen2,store,Provider);
Navigation.startSingleScreenApp({
screen:{
screen:'Screen1',
title:'Screen1',
navigatorStyle:{
navBarHidden:true
}
}
});
My challenge is to use store on different screens so that i can dispatch an action. Is there any way i can achieve that?
Note: myStore is declared in another file fulfilling all reducer, thunk configuration.

If I understand your question correctly, even though you pass store and Provider in registering each screen, you still just connect the components you want subscribed to the store and use Redux in the normal way. So:
export default connect(mapStateToProps, mapDispatchToProps)(Screen1)
I'm assuming because you tagged your question with react-redux that you understand the use of that library. If not, check out Usage with React.

You can use it using connect method below is sample demo
export default connect(mapStateToProps, mapDispatchToProps)(Screen1)
For some screen let say Screen2 if you not want to change value of store and only want to use store value then you can pass null as mapStateToProps
export default connect(null, mapDispatchToProps)(Screen2)
For some screen let say Screen3 if you want to change value(performing action) of store only but not want to display value then you can avoid passing mapDispatchToProps
export default connect(mapStateToProps)(Screen3)
sample code you can find here
https://github.com/rajscet/react_redux_basic

Related

React life cicle and AsyncStorage

I'm creating an app which passes some crucial info via AsyncStorage, but now have a problem when updating it on another screen.... Let's see:
On Screen 1 :
Load data from AsyncStorage on componentDidMount
componentDidMount() {
AsyncStorage.getItem("userChats").then((value) => {
this.setState({userChats: JSON.parse(value)});
});
}
then on Screen 2 I modify userChats.....
I'll like that when coming back again to Screen 1, the changes made on Screen 2 be reflected on Screen 1 but there are NOT as componentDidMount is not trigged again...........
What's the correct way to do it?
Thanks
componentDidMount is a life-cycle method. Navigating from Screen1 to Screen2 does NOT unmount Screen1. So, when you come back from Screen 2 to Screen 1, the Screen 1 does not mounting because it was NOT unmounted. Hence, componentDidMount is not called.
Whats's the correct way of doing this?
You should use Context API. When you load from AsyncStorage, set that value to Context as well. When you update the value, write changes to both AsyncStorage and Context.
PS: The AsyncStorage may not needed. It depends on your requirement. Most probably, you will be able to achieve this only with Context API.
Please check the following snack. It is done using hooks. You can do the same using class components.
https://snack.expo.io/3L9QSqWqt
UPDATE:
If the data to be handled is too large, it is not recommended to use Context since it saves all the data in the device RAM and consuming too much RAM may result in app crash.
To do this without using context:
(1) Define a function to retrieve data from AsyncStorage.
loadData() {
AsyncStorage.getItem("userChats").then((value) => {
this.setState({userChats: JSON.parse(value)});
});
}
(2) Call it in componentDidMount.
componentDidMount() {
this.loadData()
}
(3) When navigating to the Screen2, pass a callback function as a prop to call loadData function.
this.props.navigation.navigate('Screen2', {
onGoBack: () => this.loadData(),
});
(4) Then in the Screen2, before goBack, you can do this:
await AsyncStorage.setItem('userChats', updatedData);
this.props.navigation.state.params.onGoBack();
this.props.navigation.goBack();
Then, the loadData function is called in the screen2.
PS: Since you use state to store the retrieved data from the AsyncStorage, you can also directly load them into the Context and use. But, keep in mind that, using too much of RAM may cause app crash.

react native Redux:Even though I have used useDispatch I still do not have access to methods in the action

I've used dispatch in my component like following but I get the error modifySeatMap is not defined .But I do have modifySeatMap function defined in one of my action files. Why is this showing modifySeatMap not defined yet?
const dispatch = useDispatch();
const changeStatus=(seat)=>{
console.log("change status called with seat",seat)
seat.status="selected"
dispatch(
modifySeatMap(props.seatMap))
}
I'm attaching the screenshot of the directory structre and the method inside the action here
Why is modifySeatMap undefined here?
From your code, I do not see any issues.
I expect the issue is in how you apply your middleware.
It should look something like this.
export default store = createStore(rootReducer, applyMiddleware(thunk))

Send props between Components (no related) React-Native

I have Components directory, there is js file Timer where I have countdown Component
const [countdownTimer, setCountdownTimer] = useState(15);
This component only returns <Text>{countdownTimer}</Text> on screen.
I also have another component Description. I want to handle this state in my Description component to make some changes after time has changed. The components aren't related (they aren't imported in each other)
I tried to import Description in Timer to send value as a props like
<Description setCountdownTimer={setCountdownTimer} />
and with style hide it but display: none isn't working on Android. I also try to just hide with another method
{false && <Description setCountdownTimer={setCountdownTimer} />}
but it's also not working, I got "undefined" in console.
For your case you should take a look at React Context: https://reactjs.org/docs/context.html
Hi #Danny If I understood your question correctly, you are trying to share the countDown state between two different components, and the way you try to do it may complicate you a bit, if not I suggest you use redux which is a library designed in order to manage the global states of applications, with redux you will be able to share the states of your application with several components.
You should need to create reducers and thanks to the createStore method from `redux you will be able to use a global state to your entire application
Here it's an example of code you can improve depending on your need :
import { createStore } from 'redux';
import reducer from './reducer';
import { Provider } from 'react-redux';
const store = createStore(reducer);
export default function App () {
return (
<Provider store = {store}>
<YourMainComponent />
</Provider>
)
}
You just need to wrapp your main component with the Provider component from 'react-redux' to access to your global state and manage it as you want. See more here
https://react-redux.js.org/introduction/basic-tutorial

How to wrapper createStackNavigator with redux?

I think my question is clear. Before I start, I should show about the project structure I created myself.
I added the router logic to the project later and I think it will work better.
stack_main.js following;
import Screen from '../screens';
import {createStackNavigator} from 'react-navigation-stack';
export default createStackNavigator(
{
HomeScreen: Screen.HomeScreen,
MyEarningsScreen: Screen.MyEarningsScreen,
// TestScreen: Screen.TestScreen,
},
{
cardStyle: {
backgroundColor: '#000000',
},
},
);
In fact, if you can change the value of "cardStyle.backgroundColor" in any way, there is no need to wrap it with redux. Since redux is state management, I can't wrap the createStackNavigator function in the react-navigation module or I don't know.
I need to change the "cardStyle.backgroundColor" value every time a stack is pushed. How can I do it ?
Thank you for interest.
Why do I want this?
I created a side menu using react-native-drawer as in the image below.
In the module I used, no matter what I gave the offset props value, there were white parts of the background color; As a result of my research as a solution to this cardStyle I saw and applied.
Update to the latest version of react-navigation-stack and then use screenProps customize the colors dynamically.

use redux in existing react native project and how its affect on project

Hey guys I just started redux for my shopping cart project.
I just use that only for a global counter of cart items.
I want to know that if I use redux package in my full completed package just only for counter can I use it?
and If I use redux only for my that component which need to show cart items count. does it affect on my local state.
do I need to restructure my project to be based on redux.
and does it affect on my local state like this.state
Your redux store will not affect the value of the component assigned to this.state ;
Remember that to access the values of your redux store inside the component you need to use those functions:
const mapStateToProps = state => {
return {
yourReduxValue: state.yourReducer.yourReduxValue
};
};
const mapDispatchToProps = dispatch => {
return {
onSomeEvent: passMe => dispatch(someEvent(passMe))
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(YourScreen/YourComponent);