Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native atob() / btoa() not working without remote JS debugging

Tags:

react-native

I have a testing app in react native, and all works fine when I have enabled the debug js remotely. It works fine in device (from XCode) and simulator, after run:

react-native run ios 

The problem is that if I stop remote js debugging, the login test not works anymore.The login logic is very simple, I'm making a fetch to an api to test a login, the API endpoint is over https.

What I need to change?

Updated: This code works perfetly with JS Debug Remote Enabled, if I disable it, it not works anymore.

/**  * Sample React Native App  * https://github.com/facebook/react-native  * @flow  */  import React, { Component } from 'react' import {   AppRegistry,   StyleSheet,         View,   Button,   Alert } from 'react-native'  export default class MyClass extends Component {    constructor (props) {     super(props)     this.testFetch = this.testFetch.bind(this)   }    async testFetch () {     const email = '[email protected]'     const password = '123456'      try {       const response = await fetch('https://www.example.com/api/auth/login', {         /* eslint no-undef: 0 */         method: 'POST',         headers: {           'Accept': 'application/json' /* eslint quote-props: 0 */,           'Content-Type': 'application/json',           'Authorization': 'Basic ' + btoa(email + ':' + password)         }        })       Alert.alert('Error fail!', 'Fail')       console.log(response)     } catch (error) {       Alert.alert('Error response!', 'Ok')     }   }    render () {     return (       <View style={styles.container}>                     <Button           onPress={this.testFetch}           title="Test me!"          />                   </View>     )   } }  const styles = StyleSheet.create({   container: {     flex: 1,     justifyContent: 'center',     alignItems: 'center',     backgroundColor: '#F5FCFF'   },   welcome: {     fontSize: 20,     textAlign: 'center',     margin: 10   },   instructions: {     textAlign: 'center',     color: '#333333',     marginBottom: 5   } })  AppRegistry.registerComponent('testingReactNative', () => MyClass) 

Thanks.

like image 360
chemitaxis Avatar asked Mar 16 '17 09:03

chemitaxis


People also ask

Why is BTOA deprecated?

btoa(): accepts a string where each character represents an 8bit byte. If you pass a string containing characters that cannot be represented in 8 bits, it will probably break. Probably that's why btoa is deprecated.

What is BTOA in react JS?

The btoa() method creates a Base64-encoded ASCII string from a binary string (i.e., a string in which each character in the string is treated as a byte of binary data).


2 Answers

That's the ways I fixed it. As @chemitaxis suggests, add base-64 module from NPM:

npm i -S base-64 

Based on it, I propose a couple of ways to use it:

Importing it in files you need it

Then, you can import 'encode' and 'decode' methods using aliases, this way:

import {decode as atob, encode as btoa} from 'base-64' 

Of course, using aliases is optional.

Polyfill way

You can set atob and btoa as global variables on React Native. Then, you won't need to import them on each file you need it. You have to add this code:

import {decode, encode} from 'base-64'  if (!global.btoa) {     global.btoa = encode; }  if (!global.atob) {     global.atob = decode; } 

You need to place it at the beginning of your index.js, so that it can be loaded before another file uses atob and btoa.

I suggest you to copy it on a separate file (let's say base64Polyfill.js), and then import it on index.js

like image 61
Paolo Raez Avatar answered Sep 22 '22 23:09

Paolo Raez


Here you go (https://sketch.expo.io/BktW0xdje). Create a separate component (e.g. Base64.js), import it and it's ready to use. For instance Base64.btoa('123');

// @flow // Inspired by: https://github.com/davidchambers/Base64.js/blob/master/base64.js  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; const Base64 = {   btoa: (input:string = '')  => {     let str = input;     let output = '';      for (let block = 0, charCode, i = 0, map = chars;     str.charAt(i | 0) || (map = '=', i % 1);     output += map.charAt(63 & block >> 8 - i % 1 * 8)) {        charCode = str.charCodeAt(i += 3/4);        if (charCode > 0xFF) {         throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");       }        block = block << 8 | charCode;     }      return output;   },    atob: (input:string = '') => {     let str = input.replace(/=+$/, '');     let output = '';      if (str.length % 4 == 1) {       throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");     }     for (let bc = 0, bs = 0, buffer, i = 0;       buffer = str.charAt(i++);        ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,         bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0     ) {       buffer = chars.indexOf(buffer);     }      return output;   } };  export default Base64; 
like image 20
Samuli Hakoniemi Avatar answered Sep 25 '22 23:09

Samuli Hakoniemi