Showing posts with label react-native. Show all posts
Showing posts with label react-native. Show all posts

Wednesday, October 17, 2018

react-native-background-geolocation not giving exact location while app is in background

Leave a Comment

I have used mauron85/react-native-background-geolocation for tracking the location of the user on my react native app. It is working fine while the app is on fore ground. The location is exact on regular interval. But if the app goes to background, the location is not the same, rather is moved from the previous location even though the device is not moved. Following is my configuration -

BackgroundGeolocation.configure({     desiredAccuracy: BackgroundGeolocation.HIGH_ACCURACY,     notificationTitle: 'Background tracking',     notificationText: 'enabled',     debug: false,     startOnBoot: false,     stopOnTerminate: false,     locationProvider: BackgroundGeolocation.ACTIVITY_PROVIDER,     interval: 40000,     fastestInterval: 5000,     activitiesInterval: 10000,     stopOnStillActivity: false,     url: 'http://192.168.81.15:3000/location',     httpHeaders: {         'X-FOO': 'bar'     },     // customize post properties     postTemplate: {         lat: '@latitude',         lon: '@longitude',         foo: 'bar' // you can also add your own properties     } }); 

What should I do to fix this issue?

1 Answers

Answers 1

According the documentation, the location provider you are using BackgroundGeolocation.ACTIVITY_PROVIDER is better suited as a foreground location provider:

ACTIVITY_PROVIDER:

This one is best to use as foreground location provider (but works in background as well). It uses Android FusedLocationProviderApi and ActivityRecognitionApi for maximum battery saving.

So I would try to use DISTANCE_FILTER_PROVIDER instead:

BackgroundGeolocation.configure({      locationProvider: BackgroundGeolocation.DISTANCE_FILTER_PROVIDER }); 

This provider seems to be better suited to be used as a background location provider:

DISTANCE_FILTER_PROVIDER

It's best to use this one as background location provider. It is using Stationary API and elastic distance filter to achieve optimal battery and data usage.

Source:

https://github.com/mauron85/react-native-background-geolocation/blob/master/PROVIDERS.md

Read More

Monday, October 15, 2018

How to align a View to center without changing children's position?

Leave a Comment
<View style={{height: '100%', width: '100%'}}>    {OtherContent}    <ScrollView>       <View style={{flexDirection: 'row', flexWrap: 'wrap', padding: 20}}>            {children}       </View>    <ScrollView>  </View> 

I want the View inside ScrollView to be in center of the screen without changing it's children position

Children:

<View style={Styles.docsContainer}>             {arr.map((document, index) => {                 return (                     <TouchableOpacity key={index} style={[Style.docStyle} onPress={null}>                         <Icon name='file-text-o'/>                         <Text>{document.name}</Text>                     </TouchableOpacity>                 );             })} </View> const Styles: {     docsContainer: {        flexDirection: 'row',        flexWrap: 'wrap',        padding: 20,     },     docStyle: {       alignItems: 'center',        padding: 20,       margin: 5,       marginBottom: 10,       borderRadius: 8,       width: 170     } 

}

3 Answers

Answers 1

Indeed, we don't need parent View, we just need scrollView as flewGrow 1 which makes scrollView have full height and width as per device.

My approach:

   <ScrollView contentContainerStyle={{ flexGrow: 1, justifyContent: 'center', alignItems: 'center' }}>     <View style={{       alignItems: 'center',       justifyContent: 'center',       flex: 1,     }}>       <Text>mahesh nandam</Text>     </View>   </ScrollView> 

Try this.

Answers 2

The Viewis your ScrollView's immediate children. So you can style ScrollView using contentContainerStyle and align it in center like this.

<View style={{height: '100%', width: '100%'}}>     <ScrollView          contentContainerStyle={{              flexGrow: 1,              justifyContent: 'center',              alignItems: 'center',          }}     >      <View style={{flexDirection: 'row', flexWrap: 'wrap', padding: 20}}>          {children}      </View>     <ScrollView>  </View> 

I guess it's what you're loooking for.

Answers 3

Center Horizontally

If you only want to center the View horizontally, you can set alignItems: 'center' to ScrollView's contentContainerStyle.

<View style={{ height: '100%', width: '100%' }}>   <Text>Other content</Text>   <ScrollView contentContainerStyle={{ alignItems: 'center' }}>     <View style={{ flexDirection: 'row', flexWrap: 'wrap', padding: 20, backgroundColor: 'red' }}>       <Text>children</Text>     </View>   </ScrollView>  </View> 

The inner View is highlighted in red.

center horizontally

Center Horizontally and Vertically

In this case, you can set { flex: 1, justifyContent: 'center', alignItems: 'center' } for the same contentContainerStyle.

<View style={{ height: '100%', width: '100%' }}>   <Text>Other content</Text>   <ScrollView contentContainerStyle={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>     <View style={{ flexDirection: 'row', flexWrap: 'wrap', padding: 20, backgroundColor: 'red' }}>       <Text>children</Text>     </View>   </ScrollView>  </View> 

center horizontally and vertically

If what you expect is different layout than in either of the screenshots, please share a simple sketch of the layout.

Read More

Monday, October 8, 2018

pass environment variables during babel build phase for importing different files

Leave a Comment

I'm building a web (react with webpack & babel) and mobile apps (react-native with expo) for a project. I therefore created a common library for business logic and redux/api library.

Some code will be slightly different between web and mobile. In my case it's localStorage vs AsyncStorage, which I use for authentication among other things...

I'm trying to pass an environment variable for the build stage to switch import of certain files ex:

if(PLATFORM === 'mobile'){    import StorageModule from './mobile-storage-module` } else {    import StorageModule from './mobile-storage-module` } export default StorageModule 

Try 1

@babel/preset-env to say if it's mobile or web so that it imports different libraries depending on build like so:

My .babelrc has this:

{   "presets": [     [       "@babel/preset-env",       {         "platform": "mobile"       }     ]   ] } 

And then in local storage file I do this:

export default () => {     const platform = process.env.platform     if (platform === 'mobile') {         return import './storage-modules/storage-mobile'     }     return import './storage-modules/storage-web' } 

That didn't work, and this also didn't work for me.

Try 2

I installed react-native-dotenv and created a .env file with: PLATFORM=mobile And set the plugin in my .babelrc:

{   "presets": [     "babel-preset-expo",     "react-native-dotenv"   ] } 

And in my example file, I tried this:

import { PLATFORM } from 'react-native-dotenv' export default PLATFORM === 'mobile' ? import './storage-modules/storage-mobile' : import './storage-modules/storage-web' 

But now my build doesn't work. Any idea how I do dynamic imports during the build process that works for babel in react-native app and webpack build (also uses babel)?

2 Answers

Answers 1

First, @babel/preset-env does not do what you think it does. This is not for specifying your own variables, it is a plugin to automatically use the right target and pollyfills for the browsers you want to support.

The easiest way to get environment variables is with the webpack define plugin (which is part of webpack, so no need to install anything extra)

Just add this to your webpack config.

plugins: [     new webpack.DefinePlugin({         'process.env': {             platform: 'mobile',         },     }), ], 

Next, you can't use normal import statements inside of ifs. import gets resolved before any code runs, either on build by webpack, or in supported environments on script load. To import something on runtime, you need to use dynamic imports.

Here is an example of how this could look like.

export default new Promise(async resolve => {     resolve(         process.env.platform === 'mobile'             ? (await import('./mobile.js')).default             : (await import('./desktop.js')).default     ); }); 

You can now import from this file like you normally would, but be aware that the default export is a promise.

Answers 2

As your question's title says "during babel build phase", I assume you would like to make different builds for desktop and mobile (not one build for both and load the needed modules dynamically run-time). So I would go like this:

Define the run scripts in package.json for desktop and mobile:

"scripts": {   "devmobile": "cross-env NODE_ENV=development PLATFORM=mobile webpack --progress",   "dev": "cross-env NODE_ENV=development webpack --progress", } 

... or you can create two different webpack.config.js files for desktop and mobile builds but I think the above is easier...

Then npm run devmobile to build for mobile and npm run dev for desktop.

Since I'm on Windows I use the cross-env package but this is the recommended way to be OS independent.

Then I would use Webpack's NormalModuleReplacementPlugin:
(based on this exmaple)

In your webpack.config.js:

// defining the wanted platform for the build (comfing form the npm run script) const targetPlatform = process.env.PLATFORM || 'desktop';  // then use the plugin like this plugins: [   new webpack.NormalModuleReplacementPlugin(/(.*)-PLATFORM(\.*)/, function(resource) {     resource.request = resource.request.replace(/-PLATFORM/, `-${targetPlatform}`);   }), ] 

...then if you have these two files:

./storage-modules/storage-mobile.js ./storage-modules/storage-desktop.js 

import the needed one in your script like this:

import './storage-modules/storage-PLATFORM'; 

This way the generated build will only contain the needed file for the current PLATFORM used for the build process.

Another possible solution could be the ifdef-loader but I haven't tested it. Maybe worth to try, seems easy.


If you want one build though and import the needed module dynamically, you could do something like this in your app.js (or whatever):

// this needs to have defined when the app is running const targetPlatform = process.env.PLATFORM || 'desktop';  import(     /* webpackChunkName: "[request]" */     `./storage-modules/storage-${targetPlatform}` ).then(storageModule => {     // use the loaded module }); 

or:

(async () => {     const storageModule = await import(         /* webpackChunkName: "[request]" */         `./storage-modules/storage-${targetPlatform}`     );     // use the loaded module })(); 

For this to work Babel has to be configured.
More on Webpack with dynamic imports here.

Read More

Sunday, September 30, 2018

Share Database between React Native Apps

Leave a Comment

I am building two react native apps where i need to keep few things in common like username(login) and few other information.I tried to store using AsyncStorage (React Native Storage) and everything was working but now i need to use one common data base for both the apps as the user login success in first app then the other app should also be logged in.As Asyncstorage cannot be used in this case any other option in react native.

USE CASE FLOW

3 Answers

Answers 1

The new privacy laws do not let share the same database for 2 applications. The only thing you can do is put the database online and access to it by both apps. At least it happen in Europe. Anyway you can't use the same AsyncStorage to 2 different apps. See more here: https://stackoverflow.com/a/48806319/8898886

Answers 2

In Android, the system design do not permit that. Every app has its own sandbox. Shortly, an app can not access the database of another app.

But it could be swindled, at your risk.

You could use a sqlite database, put the database file in a shared directory, and access that file from each app. Please note that each means really each. Every app on the device could access that file, so it is not a safe place for sensible data.

The best solution, as proposed, is to use a external db, accessible from the network, to store your data. If you belive that the effort is not worth it, you could use Firebase, for example.

Answers 3

You can not use that locally. But with Firebase you can make 2 app have same Firebase Realtime database so you can share data between 2 app (event realtime). I prefer use this react-native-firebase library for React Native https://github.com/invertase/react-native-firebase

Read More

Thursday, September 20, 2018

Why is there a white “loading screen” before my page transitions in React Native?

Leave a Comment

I finally got my page transition animation working correctly (it slides from the bottom to the top of the screen) but for some reason there is a blank white "loading screen" that appears before the page does and it is ruining the whole point of the sliding animation! Can someone please tell me how to get rid of this white screen?!

Please see a video I made of this: https://youtu.be/92XGji7L-RU

const { height: deviceHeight } = Dimensions.get('window');  class OrdersScreen extends Component {     constructor(props) {         super(props);          this.state = {             offset: new Animated.Value(deviceHeight),         };     }      componentDidMount() {         Animated.timing(this.state.offset, {           duration: 350,           toValue: 0,         }).start();     }      closeModal() {         Animated.timing(this.state.offset, {           duration: 350,           toValue: -deviceHeight,         }).start(Actions.pop);     }      searchOrders = searchTerm => {         this.props.dispatch(searchOrdersWithStatus(this.props.orderStatus, searchTerm))     }      render() {         // default to Active Orders         const status = this.props.orderStatus || ORDER_TYPE_DELIVERIES;         let title = 'Order History';          if (ORDER_TYPE_DELIVERIES == status) {             title = 'Orders';         }          if (ORDER_TYPE_ISSUES == status) {             title = 'Item Alerts';         }          return (             <Animated.View style={[styles.wrapper, { transform: [{ translateY: this.state.offset }] }]}>                 <OrderHeader title={title} enableBack={false} />                  <FullWidthSearchBar placeholder='Search Orders' changeCallback={this.searchOrders} timeoutMillis={500} />                  <OrderSummaryList orderStatus={status} />             </Animated.View>         );     } }  const styles = StyleSheet.create({     wrapper: {         position: 'absolute',         top: 0,         bottom: 0,         left: 0,         right: 0,         alignItems: 'center',         justifyContent: 'flex-start'     } }); 

1 Answers

Answers 1

Your <OrderSummaryList /> component probably loads data from API - it takes some time ... on initial render data is not ready yet ... render shows `' component. This "content" is animated ... later data arrives and content is rerendered.

You can try to delay animation on start - using .delay(miliseconds) instead of start() in componentDidMount(). Find required time experimentally - too short can show loading (slow connection), too long will look like not responding app.

Read More

Wednesday, September 19, 2018

Cannot Connect to MSSQl with react-native

Leave a Comment

I have used the following package import MSSQL from 'react-native-mssql';

near the above package on hover, it shows Could not find a declaration file for module 'react-native-mssql'. 'd:/React Native Apps/Login/node_modules/react-native-mssql/index.android.js' implicitly has an 'any' type. Try npm install @types/react-native-mssql if it exists or add a new declaration (.d.ts) file containing declare module 'react-native-mssql'; module "d:/React Native Apps/Login/node_modules/react-native-mssql/index.android

I have tried installing as mentioned above but nothing works.

And in code, I am getting an error at below line. MSSQL.connect(config);

error is following undeined is not an object (evaluating '_reactNativeMssql2.default.connect')

Please tell me how do I connect to MSSQL with react-native.

0 Answers

Read More

Tuesday, September 18, 2018

Invalid sdkVersion. Valid options are 10.0.0, 11.0.0, 12.0.0, 13.0.0

Leave a Comment

I want to use this library:

https://github.com/react-community/create-react-native-app

but I got this error message:

Error: Invalid sdkVersion. Valid options are 10.0.0, 11.0.0, 12.0.0, 13.0.0, 14.0.0, 15.0.0, 16.0.0, 17.0.0, 18.0.0, 19.0.0, 20.0.0, 21.0.0, 22.0.0, 23.0.0, 24.0.0, 25.0.0, 7.0.0, 8.0.0, 9.0.0 

connected my device galaxy S4 to my mac os and I followed this methods:

$ npm install -g create-react-native-app $ create-react-native-app my-app $ cd my-app/ $ npm start 

on my screen device I got this error:

something went wrong   could not load exp://172.20.10.4:19000 network not response timed out 

1 Answers

Answers 1

This is a bug for the current package of either create-react-native-app or one of the modules it consumes. We can fix this by addressing the error directly as-stated by providing an SDK version that's actually supported. Right now, v 25.0.0 is the latest.

Open the app.json and change this line (it might be higher than v 27 by the time you read this):
"sdkVersion": "27.0.0"

to this line:
"sdkVersion": "25.0.0"

Then from that directory, run npm install to re-install the correct SDK.

Read More

Monday, September 17, 2018

infinite Render in React

Leave a Comment

I am having problem figuring out why my application is doing endless render.

Inside, My stateful component, I am calling a redux action in componentDidMount method (calling componentWillMount also do endless render)

class cryptoTicker extends PureComponent {   componentDidMount() {     this.props.fetchCoin()     // This fetches some 1600 crypto coins data,Redux action link for the same in end   }    render() {     return (       <ScrollView>         <Header />         <View>           <FlatList             data={this.state.searchCoin ? this.displaySearchCrypto : this.props.cryptoLoaded}             style={{ flex: 1 }}             extraData={[this.displaySearchCrypto, this.props.cryptoLoaded]}             keyExtractor={item => item.short}             initialNumToRender={50}             windowSize={21}             removeClippedSubviews={true}             renderItem={({ item, index }) => (               <CoinCard                 key={item["short"]}               />             )}            />         </View>       </ScrollView>     )   } } 

In CoinCard I am literally doing nothing besides this (Notice CoinCard inside Flat list)

class CoinCard extends Component {   render () {      console.log("Inside rende here")     return (         <View> <Text> Text </Text>  </View>     )     } } 

Now, When I console log in my coincard render, I can see infinite log of Inside rende here

[Question:] Can anyone please help me figure out why this could be happening?

You can click here to see my actions and click here to see my reducer.

[Update:] My repository is here if you want to clone and see it by yourself.

[Update: 2]: I have pushed the above shared code on github and it will still log endless console.log statements (if you can clone, run and move back to this commit ).

[Update:3]: I am no longer using <ScrollView /> in <FlatList /> also when I mean endless render, I mean is that it is endless (& Unecessarily) passing same props to child component (<Coincard />), if I use PureComponent, it won't log endlessly in render () { but in componentWillRecieveProps, If I do console.log(nextProps), I can see the same log passed over and over again

3 Answers

Answers 1

There are some points to note in your code.

  • The CoinCard Component must be a PureComponent, which will not re-render if the props are shallow-equal.
  • You should not render your Flatlist inside the ScrollView component, which would make the component render all components inside it at once which may cause more looping between the Flatlist and ScrollView.
  • You can also a definite height to the rendered component to reduce the number of times component is rendered for other props.
  • Another thing to note is, only props in the component are rendered on scroll bottom, based on the log statement mentioned below.

    import {Dimensions} from 'react-native'  const {width, height} = Dimensions.get('window)  class CoinCard extends React.PureComponent { render () {    console.log(this.props.item.long)  //... Check the prop changes here, pass the item prop in parent Flatlist. This logs component prop changes which will show that same items are not being re-rendered but new items are being called.   return (     <View style={{height / 10, width}}> //... Render 10 items on the screen       <Text>         Text       </Text>     </View>   )    } } 

UPDATE

This extra logging is due to the props being from the Flatlist to your component without PureComponent shallow comparison.

Note that componentWillReceiveProps() is deprecated and you should avoid them in your code. React.PureComponent works under the hood and uses shouldComponentUpdate to use shallow comparison between the current and updated props. Therefore log console.log(this.props.item.long) in your PureComponent' render will log the unique list which can be checked.

Answers 2

It seems Jacob in the above comment has managed to make the component render only twice.

This will definitely cause double initial render (and would cause an infinite render if it wasn't a PureComponent):

componentDidUpdate() {     var updateCoinData;      if (!updateCoinData) { // <- this is always true         updateCoinData = [...this.props.cryptoLoaded];         this.setState({updateCoinData: true}); // <- this will trigger a re render since `this.state.updateCoinData` is not initially true     }     ... } 

Link to the issue in your repository

Answers 3

Like izb mentions, the root cause of the pb is the business call that is done on a pure component whereas it is just loaded. It is because your component make a business decision (<=>"I decide when something must be showed in myself"). That's It is not a good practice in React, even less when you use redux. The component must shall be as stupid a possible and not even decide what to do and when to do it.

As I see in your project, you don't deal correctly with component and container concept. You should not have any logic in your container, as it should simply wrapper of a stupid pure component. Like this:

import { connect, Dispatch } from "react-redux"; import { push, RouterAction, RouterState } from "react-router-redux"; import ApplicationBarComponent from "../components/ApplicationBar";  export function mapStateToProps({ routing }: { routing: RouterState }) {     return routing; }  export function mapDispatchToProps(dispatch: Dispatch<RouterAction>) {     return {         navigate: (payload: string) => dispatch(push(payload)),     }; } const tmp = connect(mapStateToProps, mapDispatchToProps); export default tmp(ApplicationBarComponent); 

and the matching component:

import AppBar from '@material-ui/core/AppBar'; import IconButton from '@material-ui/core/IconButton'; import Menu from '@material-ui/core/Menu'; import MenuItem from '@material-ui/core/MenuItem'; import { StyleRules, Theme, withStyles, WithStyles } from '@material-ui/core/styles'; import Tab from '@material-ui/core/Tab'; import Tabs from '@material-ui/core/Tabs'; import Toolbar from '@material-ui/core/Toolbar'; import Typography from '@material-ui/core/Typography'; import AccountCircle from '@material-ui/icons/AccountCircle'; import MenuIcon from '@material-ui/icons/Menu'; import autobind from "autobind-decorator"; import * as React from "react"; import { push, RouterState } from "react-router-redux";  const styles = (theme: Theme): StyleRules => ({   flex: {     flex: 1   },   menuButton: {     marginLeft: -12,     marginRight: 20,   },   root: {     backgroundColor: theme.palette.background.paper,     flexGrow: 1   }, }); export interface IProps extends RouterState, WithStyles {   navigate: typeof push; }  @autobind class ApplicationBar extends React.PureComponent<IProps, { anchorEl: HTMLInputElement | undefined }> {   constructor(props: any) {     super(props);     this.state = { anchorEl: undefined };   }   public render() {      const auth = true;     const { classes } = this.props;     const menuOpened = !!this.state.anchorEl;     return (       <div className={classes.root}>         <AppBar position="fixed" color="primary">           <Toolbar>             <IconButton className={classes.menuButton} color="inherit" aria-label="Menu">               <MenuIcon />             </IconButton>             <Typography variant="title" color="inherit" className={classes.flex}>               Title             </Typography>              <Tabs value={this.getPathName()} onChange={this.handleNavigate} >               {/* <Tabs value="/"> */}               <Tab label="Counter 1" value="/counter1" />               <Tab label="Counter 2" value="/counter2" />               <Tab label="Register" value="/register" />               <Tab label="Forecast" value="/forecast" />             </Tabs>              {auth && (               <div>                 <IconButton                   aria-owns={menuOpened ? 'menu-appbar' : undefined}                   aria-haspopup="true"                   onClick={this.handleMenu}                   color="inherit"                 >                   <AccountCircle />                 </IconButton>                 <Menu                   id="menu-appbar"                   anchorEl={this.state.anchorEl}                   anchorOrigin={{                     horizontal: 'right',                     vertical: 'top',                   }}                   transformOrigin={{                     horizontal: 'right',                     vertical: 'top',                   }}                   open={menuOpened}                   onClose={this.handleClose}                 >                   <MenuItem onClick={this.handleClose}>Profile</MenuItem>                   <MenuItem onClick={this.handleClose}>My account</MenuItem>                 </Menu>               </div>             )}           </Toolbar>         </AppBar>       </div >     );   }   private getPathName(): string {     if (!this.props.location) {       return "/counter1";     }     return (this.props.location as { pathname: string }).pathname;   }   private handleNavigate(event: React.ChangeEvent<{}>, value: any) {     this.props.navigate(value as string);   }    private handleMenu(event: React.MouseEvent<HTMLInputElement>) {     this.setState({ anchorEl: event.currentTarget });   }    private handleClose() {     this.setState({ anchorEl: undefined });   } } export default withStyles(styles)(ApplicationBar); 

Then you will tell me: "but where do I initiate the call that will fill my list?" Well I see here that you use redux-thunk (I prefer redux observable... more complicated to learn by waaaaaaaaaaaaaaaaay more powerful), then this should be thunk that initiate the dispatch of this!

To summarize:

  • Components: the stupidest element that normally should have only the render method, and some other method handler to bubble up user events. This method only takes care of showing its properties to the user. Don't use the state unless you have a visual information that belongs only to this component (like the visibility of a popup for example). Anything that is showed or updated comes from above: a higher level component, or a container. It doesn't decide to update its own values. At best it handles a user even on a subcomponent, then bubble up an even above, and... well maybe at some point, some new properties will be given by its container!
  • Container: very stupid logic that consists in wrapping a top level component into redux for it to plug events to actions, and to plug some part of the store to properties
  • Redux thunk (or redux observable): is the one that handles the whole user application logic. This guy is the only one who knows what to trigger and when. If a part of your front end must contain the complexity, it's this one!
  • Reducers: define how to organize the data in the store for it to be as easily usable as possible.
  • The store: ideally one per top level container, the only one that contains the data that must be showed to the user. Nobody else should.

If you follow these principles, you should never face any issue like "how the hell this call is done twice? who made this call? why is this call done at this moment?"

Something else: if you use redux, use an immutability framework. Otherwise you may face issues as reducers must be pure functions. For this you can use a popular one immutable.js but not convenient at all. And the late ousider that is actually a killer: immer (made by the author or mobix).

Read More

ERROR ITMS-90680: "The binary you uploaded was invalid.”

Leave a Comment

trying to validate iOS app but got ERROR ITMS-90680: "The binary you uploaded was invalid.”

had tried adding run script at build phase but no luck, any ideas?

enter image description here

3 Answers

Answers 1

Check , you've already uploaded another app version to the store, now you'll need to create a new version and upload that.

Answers 2

It has been issued several times in Stackoverflow. Following answer may also solve your problem.

This looks promising:

https://stackoverflow.com/a/32987261/2807814

Answers 3

have you build your application for release. To do that the command is

tns build ios --release --for-device 

More info about the build command (and any other command) can be seen via

tns build ios --help 

If this does not resolve your case, please verify that you have gone through the steps described in publishing for iOS and also send us the content of your package.json file.

Read More

Saturday, September 15, 2018

React Native Fade Right/Left View on Scroll Down

Leave a Comment

I have 3 View in a ScrollView and How Can I Fade Right or Left each View on Scroll Down ?

<ScrollView >   <View>     <Text>Fade Right View 1</Text>   </View>    <View>     <Text>Fade Right View 2</Text>   </View>    <View>     <Text>Fade Right View 3</Text>   </View> </ScrollView > 

Something like this: Element Fade In on Scroll (https://codepen.io/annalarson/pen/GesqK)

2 Answers

Answers 1

I have created a small example for you, but of course you need to fine tune it to be fully functional for your purposes.

Demo

gif

Explanation

My example consists of two components. A Fade component and the actual ScrollView. The Fade Component handles the animation. The fade in animation is triggered by scrolling through the ScrollView (see handleScroll function).

Fade Component

class Fade extends Component {   constructor(props) {     super(props);     this.state = {       visible: props.visible,       visibility: new Animated.Value(props.visible ? 1 : 0),     };   };    componentWillReceiveProps(nextProps) {     if (nextProps.visible) {       this.setState({ visible: true });     }     Animated.timing(this.state.visibility, {       toValue: nextProps.visible ? 1 : 0,       duration: 500,     }).start(() => {       this.setState({ visible: nextProps.visible });     });   }    render() {     const { style} = this.props;      const containerStyle = {       opacity: this.state.visibility.interpolate({         inputRange: [0, 1],         outputRange: [0, 1],       }), // interpolate opacity        transform: [         {             translateX: this.state.visibility.interpolate({                 inputRange: [0, 1],                 outputRange: [-20, 0],             }), // interpolate translateX to create a fade in left/right         },       ],     };      const combinedStyle = [containerStyle, style];     return (       <Animated.View style={this.state.visible ? combinedStyle : containerStyle} />     );   } } 

ScrollView Snippet

handleScroll(e) {     if (e.nativeEvent.contentOffset.y > 50) { // you need to fine tune this value       this.setState({ visible: true });      }   }   <ScrollView onScroll={(e) => this.handleScroll(e) } scrollEventThrottle={8}>           <View style={{ backgroundColor: 'yellow', height: 200, marginTop: 10 }}/>           <View style={{ backgroundColor: 'yellow', height: 200, marginTop: 10 }}/>           <View style={{ backgroundColor: 'yellow', height: 200, marginTop: 10 }}/>           <Fade style={{ backgroundColor: 'red', height: 200, marginTop: 10 }} visible={this.state.visible} /> </ScrollView> 

I hope my example gives you an idea how you can achieve your intended behavior.

Answers 2

You can use onScroll like this :

<ScrollView onScroll={this.handleScroll} /> 

After that :

handleScroll = (event: Object) => {  console.log(event.nativeEvent);  // You see {layoutMeasurement, contentOffset, contentSize} in nativeEvent } 

With contentOffset, layoutMeasurement and contentSize you can rewrite Element Fade In on Scroll in React Native!

Read More

Am I handling correctly multiple projects with a common code base?

Leave a Comment

I am creating several mobile applications in react-native that share common components. I have difficulties handling the dependencies. Here is what I do, which is tedious, is there a better way?

  • A repository "common-modules" has shared components
  • Several repositories include the common one as a dependency like this:

Package.json

"dependencies": {     "common-components": "file:../common-components" }, 

I use it like that in the different apps:

import XXX from 'common-components/src/...' 

Now this is great because all other dependencies are in "common-components", but as soon as one of them has native code, I am forced to link the library again in each app.

For instance, if I use "react-native-image-picker", I have to install it again in each application and link it in XCode, edit build.gradle etc. etc.

  • It takes forever
  • Are my linked dependencies bundled twice?
  • I fear the day when I must change/upgrade one of them...

Is there a better way?

3 Answers

Answers 1

I've heard of projects that share code being managed in a monorepo. That may help managing shared code but won't solve the problem of linking native modules N times for N apps.

However, there is react-native link that should automate the process, and ease linking the native modules a lot. Note there is no need to re-link if you just upgrade a native dependency.

Alternatively, I think it should be possible to wrap multiple native modules into one. If you take a look at MainReactPackage.java in RN repo, it wraps several native modules. I imagine similar mechanism can be employed on iOS, with static libraries. Obviously, this means that it won't be easy to selectively include some modules and others not.

Answers 2

Like you said yourself it is easier to work with a duplicated codebase. To deal with that you can create your own package manager for your shared components. Make a script for each component which will add it's dependencies to package.json and configure gradle and XCode. Add a simple GUI to include your components with a single click.

This may seem like a lot of work upfront, but: - you will keep full control - once you have a script to install a component you will save time each time you use it on a new app - in the case of updates you can create a script to handle that as well

Answers 3

Requirements

This is a tutorial for advanced iOS developers. It requires practical Swift programming skills and good knowledge about iOS development. You need to know your way around the shell and about versioning software projects with Git. Please be aware that iOS is not officially supported by the Swift Package Manager and the described approach is experimental and for learning purposes only.

Motivation

The Swift Package manager shines when it comes to creating packages - it is easy and quick to create own frameworks. Perfect to create internal components as separate modules.

The integration with Xcode is very clean and lightweight: Like with Carthage, the tooling doesn’t touch your Xcode app project. The following approach uses the Swift package manager to generate an Xcode project to build the libraries. This project is manually embedded in the app project to build the dependencies:

1

The xcodeproj library from the Cocoapods project is used to modify the generated Dependencies project so it builds for iOS. This allows to customize the generated project to support anything the Swift Package Manager cannot do as of now.

Creating a HelloKit package

Run xcode-select to configure the Xcode you want to use (this tutorial has been tested with Xcode 9 and 10):  sudo xcode-select -s /Applications/Xcode-beta.app/ 

Create a folder for this tutorial:

mkdir PackageTutorial && cd PackageTutorial/ 

Create a folder for the HelloKit library we are going to create. Initialize the Swift package structure for the project and remove the files that are for Linux support:

mkdir HelloKit && cd HelloKit swift package init rm Tests/LinuxMain.swift Tests/HelloKitTests/XCTestManifests.swift 

The Swift Package manager can generate Xcode projects (swift package generate-xcodeproj), but they are generated for macOS. The following Rakefile (rake is a make-like build tool for Ruby) calls this generator and modifies the generated project to use iOS instead.

Download the example Rakefile, install the required Ruby gem xcodeproj (if you don’t have it installed already) and have a look at the script:

sudo gem install xcodeproj curl https://raw.githubusercontent.com/ralfebert/HelloKit/64097ea/Rakefile -o Rakefile cat Rakefile 

Generate the Xcode project:

rake xcodeproj 

Open the generated project:

open HelloKit.xcodeproj 

Make the struct public in Sources/HelloKit/HelloKit.swift:

public struct HelloKit {      public init() { }      public var text = "Hello, World!" } 

Run the tests with ⌘U.

The Swift package manager uses git projects and uses tags for versioning. Create a git project, commit the changes and tag the version:

git init git add . git commit -m "HelloKit library" git tag v0.1.0 

Create a repository on Github for the library and push the changes including tags to Github:

git remote add origin git@github.com:example/HelloKit.git git push --set-upstream origin master git push --tags 

Here is the example repository, the project should look like this: HelloKit library repository.

Creating the HelloApp iOS project

Create a new iOS Single View App project named HelloApp in Xcode in the PackageTutorial folder.

Create a folder Dependencies for all the package manager related files:

cd HelloApp/ mkdir Dependencies cd Dependencies 

Create a file Package.swift in the Dependencies folder. You can download an example here:

curl https://raw.githubusercontent.com/ralfebert/HelloApp/c77d6a4/Dependencies/Package.swift -o Package.swift 

Customize the dependencies properties with the Clone URL of your repository:

// swift-tools-version:4.0  import PackageDescription  let package = Package(     name: "Dependencies",     products: [         .library(name: "Dependencies", type: .dynamic, targets: ["Dependencies"]),     ],     dependencies: [         .package(url: "https://github.com/ralfebert/HelloKit.git", from: "0.1.0"),     ],     targets: [         .target(name: "Dependencies", dependencies: ["HelloKit"], path: "." )     ] ) 

Let the package manager fetch the package:

swift package update 

This should say something like:

Resolving https://github.com/example/HelloKit.git at 0.1.0 

This will download the dependency source projects into a folder .build.

Download the example Rakefile to the Dependencies folder and have a look at the script:

curl https://raw.githubusercontent.com/ralfebert/HelloApp/c77d6a4/Dependencies/Rakefile -o Rakefile cat Rakefile 

Generate the xcode project:

rake xcodeproj 

Open HelloApp.xcodeproj and drag the generated Dependencies.xcodeproj into the HelloApp.xcodeproj and add the resulting HelloKit.framework as an embedded binary for the app target:

add dependencies

Select the HelloApp scheme (the project has some other schemes that can be deleted) and build it.

Use the class from the library, f.e. in the AppDelegate:

import UIKit import HelloKit  @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate {      var window: UIWindow?       func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {         // Override point for customization after application launch.          print(HelloKit().text)          return true     } 

Run the project. (Example project on GitHub)

Updating the generated Xcode projects - Common Tasks

You can use the Rakefiles to update the generated Xcode projects. Here is example code for some common tasks:

Setting the iOS Deployment target:

project.build_configurations.each { |config|   config.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = "10.0" } 

Adding resources to a target (this might be possible in the future with the Swift package manager: SwiftPM: Need a way to include resources with targets):

target = project.targets.select {|t|t.name=="SomeTarget"}.first group = project.main_group["Sources/SomeFolder"] file = group.new_file(File.expand_path("Sources/SomeFolder/cat.png")) target.add_resources([file]) 

Setting an environment variable for a shared scheme:

scheme = Xcodeproj::XCScheme.new("SomeProject.xcodeproj/xcshareddata/xcschemes/SomeSharedScheme.xcscheme") action = scheme.launch_action env = action.environment_variables env["FOO"] = "BAR" scheme.launch_action.environment_variables = env scheme.launch_action = action scheme.save! 

Adding a system framework as linked framework (for Objective C projects) - from this gist (has some other examples of xcodeproj usage):

def add_system_frameworks(target, names)      build_phase = target.frameworks_build_phase     framework_group = target.project.frameworks_group      names.each do |name|         path = "System/Library/Frameworks/#{name}.framework"         file_ref = framework_group.new_reference(path)         file_ref.name = "#{name}.framework"         file_ref.source_tree = 'SDKROOT'         build_file = build_phase.add_file_reference(file_ref)     end  end 

More information

Nick Teissler’s article [It Looks Like You Are Trying to Use a Framework][7] describes how frameworks/shared libraries work in Xcode. 

Credit for tutorial goes to Ralf Ebert can be found here

Hope this helps you.

Read More

Tuesday, September 4, 2018

React native performance issue

Leave a Comment

I am using coincap api's to first fetch Data of about 1500+ crypto currency and then Web-socket to update the updated value of crypto Currency.

I a using redux to manage my state here

Inside My componentWillMount(), I am calling a redux action fetchCoin which fetches the value of the coin

componentWillMount() {     this.props.fetchCoin()   } 

And then In return I am doing something like this

 <FlatList            data={this.state.searchCoin ? displaySearchCrypto : this.props.cryptoLoaded}            renderItem={({ item }) => (            <CoinCard               key={item["short"]}               coinShortName = {item["short"]}               coinName = {item["long"]}               coinPrice = {item["price"].toFixed(2)}               marketCap = {(item["mktcap"]/1000000000).toFixed(4)}               percentChange = {item["perc"].toFixed(2)}               vwapData={item["vwapData"].toFixed(2)}               coinImage={"https://coincap.io/images/coins/" + item["long"] + ".png"}               /> 

Then I have a web-socket which updates the value of cryptocurrency like this

componentDidUpdate() {     var socket = openSocket('https://coincap.io');     var updateCoinData = [...this.props.cryptoLoaded];      socket.on('trades', (tradeMsg) => {       for (let i=0; i<updateCoinData.length; i++) {          if (updateCoinData[i]["short"] == tradeMsg.coin ) {          //Search for changed Crypto Value         updateCoinData[i]["long"] = tradeMsg["message"]["msg"]["long"]         updateCoinData[i]["short"] = tradeMsg["message"]["msg"]["short"]         updateCoinData[i]["perc"] = tradeMsg["message"]["msg"]["perc"]         updateCoinData[i]['mktcap'] = tradeMsg['message']['msg']["mktcap"]         updateCoinData[i]['price'] = tradeMsg['message']['msg']['price']          //Update the crypto Value state in Redux         this.props.updateCrypto(updateCoinData);            }         }      })   } 

Now, While this work, the problem is that this is slowing my app like hell since whenever the socket sends new data, it has to render every component and hence events like touch and search takes lot of time to execute.

[Question:] What should I do so that I can improve the performance of App? (Something like not using state or using DOM to update my app and so on).

[Update:] I am using https://github.com/irohitb/Crypto And these two are js files where all the logic is happening https://github.com/irohitb/Crypto/blob/master/src/container/cryptoContainer.js https://github.com/irohitb/Crypto/blob/master/src/components/CoinCard.js I have also move from map to Flatlist

2 Answers

Answers 1

Each time your component updates it starts a new socket which results in a memory leak and will cause this.props.updateCrypto(updateCoinData); to be called multiple times for the same data. This can be fixed by opening the socket in componentDidMount() and closing it in componentWillUnmount().

You can also buffer multiple record updates and change the FlatList data in one go every couple of seconds.

Edit, working example (App.js):

import React, { Component } from 'react'; import { Text, View, FlatList } from 'react-native'; import SocketIOClient from 'socket.io-client';  type Props = {}; export default class App extends Component<Props> {     constructor(props) {         super(props);          this.currencies = {};         this.state      = {             currenciesList: [],         }     }      componentDidMount() {         this.socket = SocketIOClient('https://coincap.io');          this.socket.on('trades', (tradeMsg) => {             const time = new Date();              // Store updates to currencies in an object             this.currencies[tradeMsg.message.msg.short] = {                 ...tradeMsg.message.msg,                 time: time.getHours() + ':' + time.getMinutes() + ':' + time.getSeconds(),             };              // Create a new array from all currencies             this.setState({currenciesList: Object.values(this.currencies)})         });     }      componentWillUnmount() {         this.socket.disconnect();     }      render() {         return (             <FlatList                 data={this.state.currenciesList}                 extraData={this.state.currenciesList}                 keyExtractor={(item) => item.short}                 renderItem={({item}) => <View style={{flexDirection: 'row', justifyContent: 'space-between'}}>                     <Text style={{flex: 1}}>{item.time}</Text>                     <Text style={{flex: 1}}>{item.short}</Text>                     <Text style={{flex: 1}}>{item.perc}</Text>                     <Text style={{flex: 1}}>{item.price}</Text>                 </View>}             />         );     } } 

Answers 2

The most obvious error is calling updateCrypto inside loop.

There're many standard ways to improve react app performance, the most common:

  • use usual react optimizations (shouldComponentUpdate, PureComponent - read docs)
  • use virtual lists (limit visible parts of data)

In this case I would add:

Don't process data before optimizations - f.e. formatting data that didn't changed is at least unnecessary. You can insert intermediate component (optimization layer) that will pass/update formatted data into <CoinCard /> only on 'raw data' change.

You might not need Redux at all (store data in state) when data is used in one place/simple structure. Of course you can use redux for other globally shared app state (f.e. filtering options).

Use <FlatList /> (react-native), search for sth more suitable?

Read More

Saturday, September 1, 2018

onNotification() is not fired when app is killed

Leave a Comment

i'm using https://github.com/zo0r/react-native-push-notification to get push notifications and the onNotification is working as aspected when the app is Active or in the Background i'm receiving the notification, but when i kill the app i only get the notification and the onNotification is not fired can any one please help i searched for a solution but nothing worked, i'm increasing the Android badges count when the onNotification is fired is there another way to increasing Android badges when the app is killed?

"react-native": "0.55.3", "react-native-push-notification": "3.0.2" 

my code

const options = {         // (optional) Called when Token is generated (iOS and Android)         onRegister: (token) => {             this._TOKEN = token.token;             this._addToPushChannels(channel);         },          onNotification: (notification) => {             console.log(notification);             if (notification['foreground']) {              }              //Notification from the background or when the app is killed             if (!notification['foreground']) {                 if (Platform.OS !== 'ios' && Platform.Version < 26) {                     this._messageCount++;                     // console.log('this._messageCount ', this._messageCount);                     let BadgeAndroid = require('react-native-android-badge');                     BadgeAndroid.setBadge(this._messageCount);                 }             }              // required on iOS only (see fetchCompletionHandler docs: https://facebook.github.io/react-native/docs/pushnotificationios.html)             notification.finish(PushNotificationIOS.FetchResult.NewData);          },          // ANDROID ONLY: GCM Sender ID (optional - not required for local notifications, but is need to receive remote push notifications)         senderID: this._SENDER_ID,          // IOS ONLY (optional): default: all - Permissions to register.         permissions: {             alert: true,             badge: true,             sound: true         },          // Should the initial notification be popped automatically         // default: true         popInitialNotification: true,          /**          * (optional) default: true          * - Specified if permissions (ios) and token (android and ios) will requested or not,          * - if not, you must call PushNotificationsHandler.requestPermissions() later          */         requestPermissions: true,      };      PushNotification.configure(options); 

2 Answers

Answers 1

I am not positive but when I remember correctly killing (alias force closing) an app disables the onNotification functionality in Android (GCM) Push Notification Gateway (unlike iOS/APNS). This is a Android-wise feature and intentionally created so that users who willingly force close their app dont get "bothered" with notifications. The Xtify service will be restarted and messages will be received when either the phone is restarted or the app is reopened.

What you could do is schedule notifications apriori. WhatsApp, for instances, frequently posts notifications like: "You may have new notifications" when the app is forced closed to remind the user to reopen the app.

References:

Answers 2

[1] https://stackoverflow.com/a/37845174/3607191

[2] https://stackoverflow.com/a/47857531/3607191

[3] https://github.com/dluksza/react-native-push-notification/commit/5bb95881c27b0068249c0f68bbf65e54a565fa3d#diff-54ebb78785872f03fd8e71ed2dfed620R18

You can invoke headless function on JS side to update the batch count, following is what you have to do. Here, the catch is you've to write some Java code.

  1. As explained in [2] you have to write a service extending FirebaseMessagingService.
  2. Write one more service by extending HeadlessJsTaskService to invoke headless JS function. Refer RNPushNotificationActionService.java file of [3].
  3. Now, as explained in [1] within onMessageReceived function of the service, call the native service you wrote in step 2 to invoke headless JS function. To know how to do, refer RNPushNotificationActionHandlerReceiver.java file of [3].
Read More

Monday, August 20, 2018

Why is child component not receiving updated value from parent in React Native?

Leave a Comment

When an arrow is clicked the Cart Item View needs to expand that particular view and collapse any others currently expanded. The item id of that product is passed to the parent component to update which view is to be expanded (active). Although, the id is being passed and set on the expandedItem property in the reducer this does not get updated to the child component (even though it's being passed as prop on the child component). When the child component is re-evaluated at the end the expandedViewItem is still 0, which is it's default value. Does anyone know how to get the child component to receive the updated expandedItem value? Why is it still 0??

PLEASE watch the video I made debugging this issue: https://youtu.be/qEgxqAyWDpY

Here is where the value is evaluated in the child component:

render () {  const isExpanded = product.id === this.props.expandedViewId; 

Here is the entire child component class:

export default class CartProductItem extends Component {     constructor(props) {         super(props);         this.state = {showCounter: false};     }      expandCartProductItem(id) {         this.props.onExpandClick(id);          this.setState(this.state);     }      updateDisplay = (nextProps) => {         // Null check is needed here as 0 is a valid value         if (nextProps.activeIndex !== null && nextProps.activeIndex === this.props.index) {             this.setState({                 showCounter: !this.state.showCounter             });         } else if (nextProps.activeIndex !== null && nextProps.activeIndex !== this.props.index) {             this.setState({                 showCounter: false             });         }     }      componentWillReceiveProps(nextProps) {         console.log('nextProps: ', nextProps)     }      render() {         const serverUrl = getServerAddress();         const {product} = this.props;         const price = product.iogmodPrice ? product.iogmodPrice : product.price;          const isExpanded = product.id === this.props.expandedViewId;          const imageSrc = product.imageName             ? 'https://b2b.martinsmart.com/productimages/'+ product.imageName.replace("Original", "Thumbnail")             : serverUrl + '/b2b/resources/images/nophoto.gif';          return (             <View style={styles.pContainer}>                 <CartProduct                     imageName={imageSrc}                     name={product.description}                     itemNum={product.id}                     price={price}                     pack={product.pack}                     averageWeight={product.averageWeight}                     cases={product.order_count}                 />                  <TouchableOpacity style={styles.buttonContainer} onPress={() => this.expandCartProductItem(product.id)}>                     {isExpanded ? <LineIcon name="arrow-up" style={styles.arrowIcon} /> : <LineIcon name="arrow-down" style={styles.arrowIcon} />}                 </TouchableOpacity>                  {isExpanded &&                     <ExpandHeightView height={70}>                         <View style={styles.counterContainerView}>                             <QuantityCounter style={{width: '100%'}} product={product} />                         </View>                     </ExpandHeightView>                 }             </View>         );     } } 

Here is the parent component function that passes the id to the action and the initial const declarations in the render:

expandAndCollapseItems = (id) => {     this.props.dispatch(collapseCartItemViews(id)); }  render() {     const {isLoading, displayDetails, sortCasesAsc, details, items, expandedItem} = this.props.orderInfo; 

Here is the child component in the parent component where the expandedItem variable is being passed into it:

<FlatList      data={items}     keyExtractor={(item, index) => item.id.toString()}     renderItem={({item}) => <CartProductItem product={item} expandedViewId={expandedItem} onExpandClick={(id) => this.expandAndCollapseItems(id)} />} /> 

Finally, here is the reducer function updates the app state:

    case types.SET_EXPANDED_STATE:         const id = action.id;          return {             ...state,             expandedItem: id         } 

1 Answers

Answers 1

Since you're using redux, you can just grab the expanded item id from the redux store in the child instead of passing it down from the parent.

Read More

Thursday, August 16, 2018

react-native `keyboardShouldPersistPanGesture` event that prevents the keyboard from dismissing on fast swipe events

Leave a Comment

I am building a keyboard accessory component where there will be a scroll through option above the keyboard, very similar to Twitter's keyboard. My view hiearchy is:

<InputAccessoryView>     <View style={myStyle}>         <ScrollView horizontal={true} keyboardShouldPersistTaps={'always'}            {[...Array(n).keys()].map(uid => this.renderBubble(uid) })}         </ScrollView>    </View> </InputAccessoryView> 

By putting keyboardShouldPersistTaps as always, I can make sure the press event does not dismiss the keyboard. However when I scroll through the items in ScrollView, the keyboard dismisses if I scroll too quickly, the keyboard does not dismiss if I scroll slowly. The docs here: https://facebook.github.io/react-native/docs/gesture-responder-system and here: https://facebook.github.io/react-native/docs/scrollview#onmomentumscrollbegin do not give me a way to capture a long pan event. Is there an API to do this so I scroll through the ScrollView items as fast as I want, and the keyboard will not dismiss?

1 Answers

Answers 1

check some of these sources:

https://geekhub.co.kr/react-native/releases/0.37/docs/scrollview.html

Dismissing the keyboard in a UIScrollView

https://medium.com/react-native-training/todays-react-native-tip-keyboard-issues-in-scrollview-8cfbeb92995b

https://geekhub.co.kr/react-native/releases/0.37/docs/scrollview.html

https://rebolt.callstack.com/docs/scroll-view.html

UITextView keyboardDismissMode Bug

hopefully this makes it easier for you. I know this isnt a solution that you may be looking for, but it will give you a starting point, i will continue working on this and if i find something will come back here and edit my answer.

Read More

Saturday, August 4, 2018

“Warning: Trying to remove a child that doesn't exist” Why am I getting this warning in React Native?

Leave a Comment

I'm getting a warning in React Native that I've narrowed down to one line and I've no clue why.

I've built a helper function to animate colors and values in a series like:

animate([this, "textColor", 250, "#fff1cc"]); animate([this, "rise", 250, 25], [this, "rise", 250, 0]); 

And that function is pretty simple, note the commented line causing the error:

// React Modules  import { Animated } from "react-native";  // Export  export default function func() {   step(0, arguments); }  // Extras  function step(index, args, delay = 0) {   if (args[index]) {     let argument = args[index];     index++;     handle(argument, delay, () => {       step(index, args);     });   } }  function handle(argument, delay = 0, callback) {   let that = argument[0];   let label = argument[1];   let duration = argument[2];   let endColor = argument[3];   let startColor = argument[4];   if (!that.interpolations) {     that.interpolations = {};   }   if (!that.animations) {     that.animations = {};   }   if (!that.animations[label]) {     that.animations[label] = new Animated.Value(0);   }   if (typeof endColor == "string") {     if (!startColor) {       if (that.interpolations[label]) {         startColor = JSON.stringify(that.interpolations[label]);       } else {         startColor = "#ffffff";       }     }     that.interpolations[label] = that.animations[label].interpolate({       inputRange: [0, 100],       outputRange: [startColor, endColor]     });     startValue = 0;     endValue = 100;   } else {     startValue = startColor || that.animations[label] || 0;     // setting this to that.animations[label] causes the warning     endValue = endColor;   }   Animated.timing(that.animations[label], { // warning triggered when   // Animated.timing() executes while startValue is set to that.animations[label]     toValue: startValue,      duration: 0   }).start();   Animated.timing(that.animations[label], {     toValue: endValue,     duration: duration || 500   }).start(callback); } 

Other than that warning, the code works perfectly as expected. I'd hate to just ignore a warning I don't understand though. Should I report this as a bug to the React Native repo, or is the warning warranted? Stack trace, for those interested.

2 Answers

Answers 1

Well, I am not sure one hundred percent because I couldn't reproduce your error. Following your stack trace, in L193 we have:

singleValue.stopTracking(); 

This has a chain of operations that try to untrack the Animated value.

It treats the value passed to Animated.timing as an AnimatedValue and then it reaches the point where AnimatedWithChildren try to detach the children Value nodes of your animation. The only reason I have find is that the value you have send is not a Animated Value but rather a plain primitive.

So if you follow any example of the official documentation, you will see that startValue should be new Animated.Value(0) instead of 0. So the tracking, the detaching and all the animated flow, works properly over this value.

Only in part of your application, you will assign that.animations[label], that is a new Animated.Value, but in other ones you are directly assigning a integer like in startValue = 0;

Answers 2

Try using double exclamation (!!) for the truthy conditions that you use. So instead of

if (that.interpolations[label])  

use:

 if (!!that.interpolations[label]) 
Read More

Friday, August 3, 2018

How to render multi-line Text component with white gap between lines

Leave a Comment

I am trying to replicate the following in React Native, a Text component with a white gap between lines.

span {    background: rgba(255, 235, 0);    line-height: 1.5;  }
<span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc at condimentum leo. Suspendisse potenti. Praesent ut lorem ac tortor auctor laoreet. Fusce egestas orci quis dui egestas, ac malesuada lacus feugiat. Etiam at augue vel nisl luctus dignissim. Sed iaculis nec metus vitae interdum. Vivamus tincidunt fermentum ligula, eu tincidunt orci sodales at. Ut tristique velit erat, sed malesuada sapien ornare sit amet. Nunc congue imperdiet sapien in feugiat. Aenean id ipsum quis lorem rhoncus fermentum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec ornare, risus in dictum dignissim, dui libero blandit velit, a fringilla ligula lacus quis purus. Vivamus ullamcorper lorem vel velit dignissim lacinia. Vestibulum pulvinar leo eget magna lacinia, sit amet porttitor risus cursus. Integer nec tincidunt orci. Proin maximus viverra arcu, sit amet bibendum diam sagittis ut.</span>

Adding the same CSS above to a Text component doesn't output the same as the above snippet.

1 Answers

Answers 1

Text will not behave like a span. You can do a hack for this. Use react-native-highlight-words lib and pass all text as searchWords first array element.

Read More

Wednesday, August 1, 2018

React Native IOS 11.3 - 11.4 Error: JavaScriptCore JSC::JSLock::DropAllLocks::DropAllLocks

Leave a Comment
react-native-cli: 2.0.1 react-native: 0.53.3 ios 11.3.0 - 11.4.1 

enter image description here

Crashed: WebThread 0  JavaScriptCore                 0x18a929464 JSC::JSLock::DropAllLocks::DropAllLocks(JSC::VM&) + 176 1  JavaScriptCore                 0x18a929438 JSC::JSLock::DropAllLocks::DropAllLocks(JSC::VM&) + 132 2  WebCore                        0x18b671cec SendDelegateMessage(NSInvocation*) + 360 3  WebKitLegacy                   0x18cd96c68 CallDelegate(void (*)(), WebView*, objc_object*, objc_selector*, objc_object*, objc_object*, objc_object*) + 144 4  WebKitLegacy                   0x18cd0a8d0 WebFrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader*, unsigned long, WebCore::ResourceError const&) + 276 5  WebCore                        0x18b6a0df0 WebCore::ResourceLoadNotifier::didFailToLoad(WebCore::ResourceLoader*, WebCore::ResourceError const&) + 128 6  WebCore                        0x18b6a08a8 WebCore::ResourceLoader::cancel(WebCore::ResourceError const&) + 464 7  WebCore                        0x18b6a0634 WebCore::ResourceLoader::cancel() + 64 8  WebCore                        0x18c5aa474 WebCore::CachedResource::removeClient(WebCore::CachedResourceClient&) + 264 9  WebCore                        0x18c56ea94 WebCore::MediaResource::~MediaResource() + 64 10 WebCore                        0x18c56eb44 WebCore::MediaResource::~MediaResource() + 12 11 libobjc.A.dylib                0x18268aef4 object_cxxDestructFromClass(objc_object*, objc_class*) + 148 12 libobjc.A.dylib                0x182698990 objc_destructInstance + 68 13 libobjc.A.dylib                0x1826989f8 object_dispose + 16 14 WebCore                        0x18caed6d0 -[WebCoreNSURLSessionDataTask dealloc] + 320 15 CoreFoundation                 0x1833a24e4 -[__NSDictionaryM dealloc] + 164 16 AVFoundation                   0x188ff7448 -[AVAssetCustomURLBridgeForNSURLSession dealloc] + 68 17 AVFoundation                   0x189043580 -[AVAssetResourceLoader dealloc] + 356 18 AVFoundation                   0x188f26214 -[AVURLAsset dealloc] + 248 19 WebCore                        0x18b823464 WebCore::MediaPlayerPrivateAVFoundationObjC::cancelLoad() + 240 20 WebCore                        0x18b82283c WebCore::MediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC() + 336 21 WebCore                        0x18b82333c WebCore::MediaPlayerPrivateAVFoundationObjC::~MediaPlayerPrivateAVFoundationObjC() + 12 22 WebCore                        0x18c709c00 WebCore::MediaPlayer::~MediaPlayer() + 244 23 WebCore                        0x18c709c68 WebCore::MediaPlayer::~MediaPlayer() + 12 24 WebCore                        0x18c3f0394 WebCore::HTMLMediaElement::~HTMLMediaElement() + 1336 25 WebCore                        0x18c44f2a0 WebCore::HTMLVideoElement::~HTMLVideoElement() + 176 26 JavaScriptCore                 0x18a905a5c void JSC::MarkedBlock::Handle::specializedSweep<true, (JSC::MarkedBlock::Handle::EmptyMode)1, (JSC::MarkedBlock::Handle::SweepMode)0, (JSC::MarkedBlock::Handle::SweepDestructionMode)1, (JSC::MarkedBlock::Handle::ScribbleMode)0, (JSC::MarkedBlock::Handle::NewlyAllocatedMode)1, (JSC::MarkedBlock::Handle::MarksMode)1, JSC::JSDestructibleObjectDestroyFunc>(JSC::FreeList*, JSC::MarkedBlock::Handle::EmptyMode, JSC::MarkedBlock::Handle::SweepMode, JSC::MarkedBlock::Handle::SweepDestructionMode, JSC::MarkedBlock::Handle::ScribbleMode, JSC::MarkedBlock::Handle::NewlyAllocatedMode, JSC::MarkedBlock::Handle::MarksMode, JSC::JSDestructibleObjectDestroyFunc const&) + 196 27 JavaScriptCore                 0x18a90446c void JSC::MarkedBlock::Handle::finishSweepKnowingHeapCellType<JSC::JSDestructibleObjectDestroyFunc>(JSC::FreeList*, JSC::JSDestructibleObjectDestroyFunc const&)::'lambda'()::operator()() const + 348 28 JavaScriptCore                 0x18a903fa4 void JSC::MarkedBlock::Handle::finishSweepKnowingHeapCellType<JSC::JSDestructibleObjectDestroyFunc>(JSC::FreeList*, JSC::JSDestructibleObjectDestroyFunc const&) + 320 29 JavaScriptCore                 0x18a903e58 JSC::JSDestructibleObjectHeapCellType::finishSweep(JSC::MarkedBlock::Handle&, JSC::FreeList*) + 32 30 JavaScriptCore                 0x18a68597c JSC::MarkedBlock::Handle::sweep(JSC::FreeList*) + 372 31 JavaScriptCore                 0x18a67c064 JSC::IncrementalSweeper::sweepNextBlock() + 132 32 JavaScriptCore                 0x18a05e7fc JSC::IncrementalSweeper::doWork() + 72 33 JavaScriptCore                 0x18a949864 JSC::JSRunLoopTimer::timerDidFireCallback(__CFRunLoopTimer*, void*) + 76 34 CoreFoundation                 0x18347baa8 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 28 35 CoreFoundation                 0x18347b76c __CFRunLoopDoTimer + 864 36 CoreFoundation                 0x18347b010 __CFRunLoopDoTimers + 248 37 CoreFoundation                 0x183478b60 __CFRunLoopRun + 2168 38 CoreFoundation                 0x183398da8 CFRunLoopRunSpecific + 552 39 WebCore                        0x18b65c2d4 RunWebThread(void*) + 592 40 libsystem_pthread.dylib        0x1830f9220 _pthread_body + 272 41 libsystem_pthread.dylib        0x1830f9110 _pthread_body + 290 42 libsystem_pthread.dylib        0x1830f7b10 thread_start + 4 

The app displays some html content in an WebView. All I know about this crash is that it could be related to embedded videos widgets:

https://forums.developer.apple.com/thread/101477

Is this bug related to React Native platform? Would an update of RN fix the issue?

This issue could be related to Javascript core crash when using YouTube iframe player in UIWebView in iOS 11.3 because of the React Native WebView...

The app content which is displayed in webview can be normal html text or instagram, facebook or youtube scripts/iframes ...

0 Answers

Read More

Monday, July 23, 2018

Create Native SDKs with React Native

Leave a Comment

I want to create client libraries for my backend for iOS and Android. They will be using native services like location services.

Instead of creating a seperate SDK for each, I was wondering if I would use react native to create the SDK, and then compile(eject) it to a native iOS pod or android aar library. Is this possible to achieve with react native, and if yes, how can this be achieved.

If not react native, then is there any cross platform framework which allows this?

1 Answers

Answers 1

If understood correctly, you want to develop react native libs then use in none react native projects. For example adding them to gradle or pods, But it's not available.

Because react native platform is different and needs bunch of other dependencies to be run. It's looks like running another engine inside the other one.

You can build SDK's based on Hybrid/Native frameworks and use them in those frameworks but you can't export them and use like native libraries(pod/gradle).

Except C++ programming for cross platform purposes, you should search in github or other repositories to find specific types of libraries that you need.

Read More

Tuesday, July 17, 2018

How could I perform a pan to Camera in React Native?

Leave a Comment

In apps such as Instagram, you can pan left (on home screen) to show the camera VC. The camera comes in as you pan. How can I implement this in React Native?

3 Answers

Answers 1

You can listen for pan events with PanResponder and navigate to desired screen or run an action or similar to open up the camera.

PanResponder

PanResponder reconciles several touches into a single gesture. It makes single-touch gestures resilient to extra touches, and can be used to recognize simple multi-touch gestures.

By default, PanResponder holds an InteractionManager handle to block long-running JS events from interrupting active gestures.

It provides a predictable wrapper of the responder handlers provided by the gesture responder system. For each handler, it provides a new gestureState object alongside the native event object:

onPanResponderMove: (event, gestureState) => {} 

Answers 2

You can use PanResponder's onPanResponderGrant and onPanResponderRelease events to check if the movement is a left pan, then open the camera with react-native-camera or Expo's Camera / ImagePicker modules.

Working demo: https://snack.expo.io/SJCGFC477

import React, { Component } from 'react'; import { Text, PanResponder, Alert } from 'react-native'; import { ImagePicker, Permissions } from 'expo';  export default class App extends Component {   panResponder = PanResponder.create({     onStartShouldSetPanResponder: () => true,     onPanResponderGrant: e => {       this.start = e.nativeEvent.pageX;     },     onPanResponderRelease: e => {       if (this.start - e.nativeEvent.pageX > 100) {         Promise.all([           Permissions.askAsync(Permissions.CAMERA),           Permissions.askAsync(Permissions.CAMERA_ROLL),         ]).then(([{ status: status1 }, { status: status2 }]) => {           if (status1 !== 'granted' && status2 !== 'granted') {             Alert.alert('Permission not granted');             return;           }           ImagePicker.launchCameraAsync().catch(e =>             Alert.alert('Failed to launch camera', e.message)           );         });       }     },   });    render() {     return (       <Text         {...this.panResponder.panHandlers}         style={{ flex: 1, paddingTop: '50%' }}>         Pan left to open camera       </Text>     );   } } 

Answers 3

Likely the simplest way to accomplish this would be to render a view offscreen which has the same dimensions as your current view. Presumably using Dimensions.get('window') but your use case might differ slightly.

The key to setting it offscreen would be to position it absolutely, and set the value for left to the negative value of your screen width. However, to accomplish the transition, you'd want to have this value be an Animated.Value initialized to that negative screen width I'd mentioned.

Finally, as others have suggested, you'll need to implement a PanResponder on your initially visible view that would change the value of the left style on the absolutely positioned view with the camera. You'd want that camera view to be already active so your transition would look smooth.

Here's some pseudocode, I could help with a more fleshed out solution if this is the path you'd want to pursue for this question

// in constructor this.state = {   leftValue: new Animated.Value(-screenWidth) }  // in render <View style={styles.initialView} /> <Animated.View   style={{     position: 'absolute',     top: 0,     left: this.state.leftValue,     width: screenWidth,     height: screenHeight,   }} >   {cameraImplementation} </Animated.View> 
Read More