React-Native using Components without render - gps

I am new to react-native and am trying to build a Map component that relies on a GPS component. (I am actually not even sure if 'component' is the correct word)
I want to render the map using a UI, but I also need the GPS to get the location information.
Now, how can I create a GPS class including all the GPS logic, calling only a single function to update the location on the page page? Or more specifically, how can I separate the GPS code into a new file without having to call a <GPSComponent /> within the render method of the map-component?
To be more specific with the code example, I put it on CodePen here https://codepen.io/yeni/pen/WOrjJx

Just put your GPS class in a separate file. The class should not extend Component.
Then import your GPS class in your UI Component (e.g. import gps from './gps') and use it :)

another possible way is to return null inside render method
export default class GPSComponent extends React.Component{
constructor(props){
super(props);
// Do some stuff
}
someFunctions() { ... }
render(){
return null;
}
}

Related

how to call a function in other component in react-native

I'm working on a board game, which uses a long code to generate data to the board.
Currently I have 2 components. Home and Board. Home only has a Welcome message and a button to navigate into Board.
Currently Board has the function to generate the data, but I'd like to move this function to other component, generate the data there and return an array to my Board component. This new function/component won't do anything else but return an array to Board.
Is it possible to do in React-Native? I'm coming from other programming logic, and I cannot figure out how to achieve this.
Thank you.
you can use props in React Native, this link for documentation and this for passing function in props to component
Use ref.
Class A extends React.Component{
returnArray = () => return ['a','b','c'];
render(){....}
};
In other class
Class B extends React.Component{
getArray = () => {
const array = this.comp.returnArray(); //do whatever you want to do with the array
}
render(){
return <A ref={ref=>this.comp=ref}/>
}
}
In the function component you can export you function like:
export const arrayFunction = () => {
// array generation code
return array
}
and in your board component you can import the function from js file and use it like this.
const array = arrayFunction()
this constant array will have the array returned from the function.
Perhaps my best suggestion is that you need to use redux for the management of functions and states on several components and can be used anywhere (global) for the documentation, it can be seen clearly enough at:Reudux Official

dynamic text change in react-native

Hi I am looking for the solution to change text dynamically.
I am writing code to show processing results on screen.
After some googling, I found there is a code to update text dynamically as follows.
But I would like to update text without any internal event. I want to change text from outside of the class. But I don't know how to implement it as I am a javascript and react-native beginner. There are other classes to process some functions so that I need to show the updated results using Results class which is an another component of the screen.
How can I deliver 'result' to Results class and how to update it dynamically and automatically?
class Results extends Component {
constructor() {
super()
this.state = {
log: 'Processing results'
}
}
updateText = (result) => {
this.setState({log: result})
}
render() {
return (
<View>
<Text onPress = {this.updateText}>
{this.state.log}
</Text>
</View>
)
}
}
This sounds to me that props can solve your problem.
Basically when you try to render Results class, pass along the value as a prop like below:
<Results dynamicText='HI' />
Then, from your Results class, access this external value via this.props.dynamicText as below
class Results extends Component {
render() {
return (
<View>
<Text>
{this.props.dynamicText}
</Text>
</View>
)
}
}
In addition to what #Issac answered, you can also hook up your current class to Redux and dispatch actions from another class to force state changes.
React Native and ReactJS has a different concept of how classes react to each other. Most other languages use inheritance based interactions to affect changes in classes other than itself. React itself is more composition based where changing the value/state/variable of one class requires either a state change or a prop change. The caveat to that us using Redux, which utilizes an overarching Store where any component that's connected to it can pull values or dispatch actions to change values.

React Native - Handle parent state from child component (custom component) without add function in parent

I have read this answer, but I want to change the structur of code a little bit,
actually I want to set parent state from child component but i don't want to add any function in parent component
actually the expected result looks like :
class Parent extends React.Component {
constructor(props) {
super(props)
this.state={modalVisible:false}
}
render() {
return (
<Child modalVisible={this.state.modalVisible} />
<Button onClick={()=>this.setState({modalVisible:true})/>
)
}
}
class Child extends React.Component {
handler(e) {
//handle parent moadlVisible state to false again
}
render() {
return
<Modal
modalVisible = {this.props.modalVisible}>
<Button title="Close Modal" onPress={()=>this.handler(e)}/>
</Modal>
}
}
so I want to make it easy to call the child component without add some function in parent to handle the child component itself, even for closing the modal of child component
Is there a way to achieve what I want?
If you don't want any connection between the 2 components at all, then you may have to use a global state store, such as redux.
Docs can be found here:
https://redux.js.org/introduction
Redux creates a global state instead of local state between all of the components. It does require a little configuration but once you have it fully integrated, you can handle your scenario. Also as your components grow, it'll be easier to keep track of state.
Why can't I just use events?
Quote in a question here..
react.js custom events for communicating with parent nodes
The React way would be to pass callbacks down to children explicitly
via props — . There's no support for custom events w/ bubbling in
React.
The reactive programming abstraction is orthogonal:
Programming interactive systems by means of the observer pattern is
hard and error-prone yet is still the implementation standard in many
production environments. We present an approach to gradually deprecate
observers in favor of reactive programming abstractions. Several
library layers help programmers to smoothly migrate existing code from
callbacks to a more declarative programming model.
A horrid way to do it in my eyes would possibly be to use Async Storage
to store the key value, but I'm not going to suggest that.

Large components as sections in VirtualizedList/etc?

If I want to display a bunch of heterogenous data in a virtualized list, it seems like the default way to do it is have the parent component gather up all the data so that it can create the sections to supply to the list component.
Is there any way to avoid requiring the parent component from doing this? I'd like to decouple the parent component from the data gather part, so that all it has to do is declare it has such and such components, and then those components would be responsible for gathering the data.
This would be exceedingly simple if it were a ScrollView:
<ScrollView>
<SectionA>
<SectionB>
<SectionC>
</ScrollView>
However, to leverage the performance gains of a VirtualizedList, if each section is large, I would need to pass in the individual data of each section into the VirtualizedList. I'm not sure how to do this or if it's possible.
Not sure if this is idiomatic or a gross React anti-pattern, but the way I solved it was to implement each section as purely headless data Component.
export type SectionDataComponentProps = {
onDataChanged?: () => void, // call this whenever the data updates.
}
export class SectionDataComponent<P : SectionDataComponentProps, S, ItemT> extends React.PureComponent<P, S> {
// Implemented by subclasses
getSectionData() : Array<SectionT<ItemT>> {
// returns an array of sections for a SectionList...
}
render() {
// business logic component only.
return null;
}
}
The parent component keeps track of them through the use of ref, and then calls getSectionData() as needed.

How to use global variables in React Native?

In React Native I want to use global variables when I am moving between different screens
Can anyone help me how to achieve it?
The global scope in React Native is variable global. Such as global.foo = foo, then you can use global.foo anywhere.
But do not abuse it! In my opinion, global scope may used to store the global config or something like that. Share variables between different views, as your description, you can choose many other solutions(use redux,flux or store them in a higher component), global scope is not a good choice.
A good practice to define global variable is to use a js file. For example global.js
global.foo = foo;
global.bar = bar;
Then, to make sure it is executed when project initialized. For example, import the file in index.js:
import './global.js'
// other code
Now, you can use the global variable anywhere, and don't need to import global.js in each file.
Try not to modify them!
Try to use global.foo = bar in index.android.js or index.ios.js, then you can call in other file js.
You can use the global keyword to solve this.
Assume that you want to declare a variable called isFromManageUserAccount as a global variable you can use the following code.
global.isFromManageUserAccount=false;
After declaring like this you can use this variable anywhere in the application.
You can consider leveraging React's Context feature.
class NavigationContainer extends React.Component {
constructor(props) {
super(props);
this.goTo = this.goTo.bind(this);
}
goTo(location) {
...
}
getChildContext() {
// returns the context to pass to children
return {
goTo: this.goTo
}
}
...
}
// defines the context available to children
NavigationContainer.childContextTypes = {
goTo: PropTypes.func
}
class SomeViewContainer extends React.Component {
render() {
// grab the context provided by ancestors
const {goTo} = this.context;
return <button onClick={evt => goTo('somewhere')}>
Hello
</button>
}
}
// Define the context we want from ancestors
SomeViewContainer.contextTypes = {
goTo: PropTypes.func
}
With context, you can pass data through the component tree without having to pass the props down manually at every level. There is a big warning on this being an experimental feature and may break in the future, but I would imagine this feature to be around given the majority of the popular frameworks like Redux use context extensively.
The main advantage of using context v.s. a global variable is context is "scoped" to a subtree (this means you can define different scopes for different subtrees).
Do note that you should not pass your model data via context, as changes in context will not trigger React's component render cycle. However, I do find it useful in some use case, especially when implementing your own custom framework or workflow.
Set up a flux container
simple example
import alt from './../../alt.js';
class PostActions {
constructor(){
this.generateActions('setMessages');
}
setMessages(indexArray){
this.actions.setMessages(indexArray);
}
}
export default alt.createActions(PostActions);
store looks like this
class PostStore{
constructor(){
this.messages = [];
this.bindActions(MessageActions);
}
setMessages(messages){
this.messages = messages;
}
}
export default alt.createStore(PostStore);
Then every component that listens to the store can share this variable
In your constructor is where you should grab it
constructor(props){
super(props);
//here is your data you get from the store, do what you want with it
var messageStore = MessageStore.getState();
}
componentDidMount() {
MessageStore.listen(this.onMessageChange.bind(this));
}
componentWillUnmount() {
MessageStore.unlisten(this.onMessageChange.bind(this));
}
onMessageChange(state){
//if the data ever changes each component listining will be notified and can do the proper processing.
}
This way, you can share you data across the app without every component having to communicate with each other.
If you just want to pass some data from one screen to the next, you can pass them with the navigation.navigate method like this:
<Button onPress={()=> {this.props.navigation.navigate('NextScreen',{foo:bar)} />
and in 'NextScreen' you can access them with the navigation.getParam() method:
let foo=this.props.navigation.getParam(foo);
But it can get really "messy" if you have more than a couple of variables to pass..
The way you should be doing it in React Native (as I understand it), is by saving your 'global' variable in your index.js, for example. From there you can then pass it down using props.
Example:
class MainComponent extends Component {
componentDidMount() {
//Define some variable in your component
this.variable = "What's up, I'm a variable";
}
...
render () {
<Navigator
renderScene={(() => {
return(
<SceneComponent
//Pass the variable you want to be global through here
myPassedVariable={this.variable}/>
);
})}/>
}
}
class SceneComponent extends Component {
render() {
return(
<Text>{this.props.myPassedVariable}</Text>
);
}
}