Quantcast
Channel: Active questions tagged react-native+typescript - Stack Overflow
Viewing all 6406 articles
Browse latest View live

Why are rest parameters undefined in TypeScript?

$
0
0

I have a React Native app that I'm programming with TypeScript (3.6.3). I have the following code (the actual code is from an API library but this is a minimum reproducable example):

class Base{
    someVal: string[];
    constructor() {
        this.someVal = [];
    }
    someMethod<T extends Base>(this: T, ...someArgs:string[]){
        debugger;
        this.someVal = someArgs;
    }
}

class Derived extends Base{

}

let myVar = new Derived().someMethod('hello');

The code exactly mimics the library code, and behaves the same (erroneous) way. There are no compiler errors or warnings. When I run the code, I expect someArgs to be ['hello'], but it is undefined. Also, I've got an arguments array which contains the actual value of ['hello']:

enter image description here

At this point the code (which is transpiled by Babel on the fly) is acting like Javascript (hence, the undefined actual variable and the phantom arguments variable). Why isn't it transpiled correctly and how do I fix it? (I'm on Babel core/runtime 7.6.2)

Here's the relevant code from the generated index.bundle:

    var Base = function () {
    function Base() {
      (0, _classCallCheck2.default)(this, Base);
      this.someVal = [];
    }

    (0, _createClass2.default)(Base, [{
      key: "someMethod",
      value: function someMethod() {
        debugger;

        for (var _len = arguments.length, someArgs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
          someArgs[_key - 1] = arguments[_key];
        }

        this.someVal = someArgs;
      }
    }]);
    return Base;
  }();

  var Derived = function (_Base) {
    (0, _inherits2.default)(Derived, _Base);

    function Derived() {
      (0, _classCallCheck2.default)(this, Derived);
      return (0, _possibleConstructorReturn2.default)(this, (0, _getPrototypeOf2.default)(Derived).apply(this, arguments));
    }

    return Derived;
  }(Base);

  var myVar = new Derived().someMethod('hello');

Network request failed with react-native and graphql

$
0
0

I have a react-native app, that has a GraphQL client to get the content from my server on Heroku.

This is how my GraphQL client on the app looks like:

// API_ENDPOINT: https://my-app.herokuapp.com
const httpLink = new HttpLink({ uri: config.API_ENDPOINT });

const authLink = setContext((_, { headers }) => ({
  headers: {
    ...headers,
    'x-api-key': config.API_TOKEN,
  },
}));

const errorLink = onError(({ operation, response, graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, locations, path, code }: any) => {
      errorLog(
        `GraphQL error, operation: ${operation.operationName}, variables: ${JSON.stringify(
          operation.variables,
        )}, message: ${JSON.stringify(message)}, location: ${JSON.stringify(locations)}, path: ${JSON.stringify(
          path,
        )}, code: ${JSON.stringify(code)}`,
      );
    });
  }

  if (networkError) {
    errorLog(
      `Network error, error: ${networkError}, operation: ${operation.operationName}, variables: ${JSON.stringify(
        operation.variables,
      )}, response: ${JSON.stringify(response)}, code: ${JSON.stringify(
        get(networkError, 'statusCode'),
      )}, graphqlerrors: ${JSON.stringify(graphQLErrors)}`,
    );
  }
});

const link = ApolloLink.from([errorLink, authLink, httpLink]);
const cache = new InMemoryCache();

export const client = new ApolloClient({
  link,
  cache,
  defaultOptions: {
    query: {
      errorPolicy: 'ignore',
    },
  },
});

then to fetch the data and persist it on the user device, I use mobx-state-tree, it looks like this:

fetch: flow(function* fetch(): any {
  self.isLoading = true;

  const { data, loading } = yield client.query({
    query: QUERY,
    fetchPolicy: 'network-only',
  });

  if (!data) {
    self.isLoading = false;

    return;
  }

  try {
    self.now = NowModel.create(data);
  } catch (e) {
    errorLog(`Cannot create NowModel: ${e}, ${JSON.stringify(now)}`);
  }

  self.isLoading = loading;
}),

Alright, that was the introduction, let's talk about the problem now.

I tried the app on multiple devices, in release mode, and I didn't have any issue. I'm using Sentry to get issues reports, and I received a lot of error related to networks issues (and with other queries):

Network error, error: TypeError: Network request failed, operation: myQuery, variables: undefined, response: undefined, code: undefined, graphqlerrors: undefined

I also checked logs on the server and I don't have any issues or errors on the requests, they all respond with status 200.

Things that I'm suspecting it's that it could be related to fetchPolicy: 'network-only' or errorPolicy: 'ignore' without being sure. Could it also be that when the app goes into the background the user device, it goes into a weird state for the graphql client? or could it be that the user is trying to load data when he is not connected to the internet?

thanks in advance,

Animated view squeeze the text components after animation in react-native app

$
0
0

After animation my text components squeezes inside of Animated.View. For example if i have 4 lines of text and only 2 of them just shows on the screen. And i made a lot of manipulation like put flex=1, maxHeight to the parent and nothing is working. The best way what i have found is to change minHeight of AnimatedView. But i think it is not a good idea to implement dynamic height that depends on the text length. Can you recommend me please a good way to do it.enter image description here.

const vars = {
  duration: 500,
  offset: 56,
};

export class Notification extends React.Component<NotificationProps> {
  public state = {
    offset: new Animated.Value(-vars.offset),
    opacity: new Animated.Value(0),
  };

  private _timeout: any;

  public componentDidMount() {
    const timeout = -moment().diff(this.props.closeTime);
    this._timeout = setTimeout(this._close, timeout);

    Animated.parallel([
      Animated.timing(this.state.offset, {
        toValue: 8,
        duration: vars.duration,
      }),
      Animated.timing(this.state.opacity, {
        toValue: 1,
        duration: vars.duration,
      }),
    ]).start();
  }

  public componentWillUnmount() {
    clearTimeout(this._timeout);
  }

  public componentDidUpdate(prevProps: NotificationProps, prevState: any) {
    const { itemIndex } = this.props;
    const timeout = -moment().diff(this.props.closeTime);
    clearTimeout(this._timeout);

    if (itemIndex && itemIndex >= 2) {
      this._close(true);

      return;
    }

    this._timeout = setTimeout(this._close, timeout);
  }

  public render() {
    const { type, title, message, itemIndex = 0 } = this.props;
    const containerStyle = type ? (SS as any)['notificationType' + type.capitalize()] : null;
    const animatedStyle = {
      marginTop: this.state.offset,
      opacity: this.state.opacity,
      zIndex: 10 - itemIndex,
    };

    return (
      <Animated.View style={animatedStyle}>
        <TouchableOpacity style={[SS.notification, containerStyle]} activeOpacity={1} onPress={this._onPress}>
          <Row flex={1}>
            <Row flex={1}>
              <Row alignSelf={'center'} flex={1}>
                {!!title && <Text textStyle={'textLine'} color={colors.base}>{title}</Text>}
                <Text numberOfLines={3} textStyle={'textLine'} color={colors.base} wrap>{message}</Text>
              </Row>
            </Row>
            <ButtonIcon name={'IconClosePopup'} color={colors.base} fontSize={10} onPress={this._onPress} />
          </Row>
        </TouchableOpacity>
      </Animated.View>
    );
  }

  private _onPress = () => {
    this._close(false);
  };

  private _close = (isThird: boolean = false) => {
    Animated.parallel([
      Animated.timing(this.state.offset, {
        toValue: isThird ? vars.offset : -vars.offset,
        duration: vars.duration,
      }),
      Animated.timing(this.state.opacity, {
        toValue: 0,
        duration: vars.duration,
      }),
    ]).start(() => this.props.onPress());
  };
}

const SS = EStyleSheet.create({
  notification: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: colors.base,
    justifyContent: 'space-between',
    borderRadius: 8,
    paddingHorizontal: 12,
    paddingTop: 21,
    paddingBottom: 19,
    marginHorizontal: 12,
    minHeight: vars.offset,
  },
  notificationTypeAlert: { backgroundColor: colors.negativeLight },
  notificationTypeSuccess: { backgroundColor: colors.positiveLight },
  notificationTypeInfo: { backgroundColor: colors.negativeLight },
});

what is the proper return type for the "onPress" of my Navigation Button?

$
0
0

tsc is alerting me to add return types after the render method, and after onPress of my class component.

I've tried using React.ReactNode as the render return type, which makes the alert go away, but React.ReactChild also works (what's the difference? )

For the onPress event, i've tried void, which makes the return type happy, but I'm unsure if this is the correct return type to enter.

I've looked at the typescript cheatsheet on Github, but I can't find the opinionated definitive way.

export interface Props {
  navigation;
}

class HomeScreen extends React.Component<Props> {
  render(): React.ReactNode { // HERE
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <Text>Home Screen</Text>
        <Button title="Go to Details" onPress={(): void =>  this.props.navigation.navigate('Details')} /> // HERE 
      </View>
    );
  }
}

[TypeError: s.httpService.post is not a function.line: 541, column: 2099, sourceURL: 'index.android.bundle' }

$
0
0

I am getting following error while running react native application in release mode,

[TypeError: s.httpService.post is not a function. (In 's.httpService.post(o,l,!1)', 's.httpService.post' is undefined)] line: 541, column: 2099, sourceURL: 'index.android.bundle' }

I am using Typescript and HttpService class is created by me. In debug mode, all works fine.

export class HttpService extends BaseService {
 constructor() {
        super();
   }

   async post(url: string, body: any) {

   }
}

I am calling post function from another service class as follows,

export class UserService extends BaseService {
    httpService: HttpService | undefined;

    constructor() {
        super();
    }

    init() {
        this.httpService = ServiceRepository.instance().resolve<HttpService>(HttpService.name);
    }

    async getUser(userId: string): Promise<UserInfo> {
        var url = '<API URL>';
        var body = {
            apiKey: Config.apiKey,
            licenceKey: Config.licenseKey,
            userId: userId
        };

        return await this.httpService!.post(url, body);
    }
}

What can be the issue? Facing similar problems in release mode in other places as well.

package.json

"dependencies": {
    "react": "16.9.0",
    "react-native": "0.61.2",
    "react-native-document-picker": "^3.2.4",
    "react-native-router-flux": "^4.0.6",
    "react-native-view-pdf": "^0.10.1"
  },
  "devDependencies": {
    "@babel/core": "^7.6.4",
    "@babel/runtime": "^7.6.3",
    "@react-native-community/eslint-config": "^0.0.5",
    "@types/jest": "^24.0.19",
    "@types/react": "^16.9.9",
    "@types/react-native": "^0.60.21",
    "@types/react-test-renderer": "^16.9.1",
    "babel-jest": "^24.9.0",
    "eslint": "^6.5.1",
    "jest": "^24.9.0",
    "metro-react-native-babel-preset": "^0.56.0",
    "react-native-typescript-transformer": "^1.2.13",
    "react-test-renderer": "16.9.0",
    "ts-jest": "^24.1.0",
    "typescript": "^3.6.4"
  },

tsconfig.json

"compilerOptions": {
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "jsx": "react",                           /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    "strict": true,                           /* Enable all strict type-checking options. */
    "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
  }

build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = "28.0.3"
        minSdkVersion = 21
        compileSdkVersion = 28
        targetSdkVersion = 28
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:3.4.2")

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url("$rootDir/../node_modules/react-native/android")
        }
        maven {
            // Android JSC is installed from npm
            url("$rootDir/../node_modules/jsc-android/dist")
        }

        google()
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}

build.gradle

project.ext.react = [
    entryFile: "index.js",
    enableHermes: false,  // clean and rebuild if changing
]

apply from: "../../node_modules/react-native/react.gradle"

/**
 * Set this to true to create two separate APKs instead of one:
 *   - An APK that only works on ARM devices
 *   - An APK that only works on x86 devices
 * The advantage is the size of the APK is reduced by about 4MB.
 * Upload all the APKs to the Play Store and people will download
 * the correct one based on the CPU architecture of their device.
 */
def enableSeparateBuildPerCPUArchitecture = false

/**
 * Run Proguard to shrink the Java bytecode in release builds.
 */
def enableProguardInReleaseBuilds = false

/**
 * The preferred build flavor of JavaScriptCore.
 *
 * For example, to use the international variant, you can use:
 * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
 *
 * The international variant includes ICU i18n library and necessary data
 * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
 * give correct results when using with locales other than en-US.  Note that
 * this variant is about 6MiB larger per architecture than default.
 */
def jscFlavor = 'org.webkit:android-jsc:+'

/**
 * Whether to enable the Hermes VM.
 *
 * This should be set on project.ext.react and mirrored here.  If it is not set
 * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
 * and the benefits of using Hermes will therefore be sharply reduced.
 */
def enableHermes = project.ext.react.get("enableHermes", false);

android {
    compileSdkVersion rootProject.ext.compileSdkVersion

    dexOptions {
        javaMaxHeapSize "4G"
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        applicationId "id.idi.ekyc"
        minSdkVersion 21
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 1
        versionName "1.0"
    }
    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
        }
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
        release {
            if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
                storeFile file(MYAPP_UPLOAD_STORE_FILE)
                storePassword MYAPP_UPLOAD_STORE_PASSWORD
                keyAlias MYAPP_UPLOAD_KEY_ALIAS
                keyPassword MYAPP_UPLOAD_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.debug
            minifyEnabled false
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://facebook.github.io/react-native/docs/signed-apk-android.
            signingConfig signingConfigs.release
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
    }
    // applicationVariants are e.g. debug, release
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            // For each separate APK per architecture, set a unique version code as described here:
            // https://developer.android.com/studio/build/configure-apk-splits.html
            def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
            def abi = output.getFilter(OutputFile.ABI)
            if (abi != null) {  // null for the universal-debug, universal-release variants
                output.versionCodeOverride =
                        versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
            }

        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.facebook.react:react-native:+"  // From node_modules

    implementation 'com.android.support:support-v4:28.0.0'
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.android.volley:volley:1.1.1'

    if (enableHermes) {
        def hermesPath = "../../node_modules/hermes-engine/android/";
        debugImplementation files(hermesPath + "hermes-debug.aar")
        releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
        implementation jscFlavor
    }
}

// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
    from configurations.compile
    into 'libs'
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

Make TypeScript function accept Redux connected component

$
0
0

I've got a React Native project where I've got a Screen class, and HomeScreen, MyProfileScreen classes derived from it (I know, composition preferred over inheritance, but let's keep that argument somewhere else) (irrelevant parts redacted, but notice the identifier getter function, I'll come to that):

export default class Screen<P = {},S = {},SS = {}> extends Component<P,S,SS> {
    static get identifier(){
        return this.name;
    }     
}

Then, in my home screen and profile screen (which basically has the same structure with home screen):

export default class HomeScreen extends Screen<HomeScreenProps & HomeScreenDispatchProps>{
    [...]
}

Now, I'm writing a function where it accepts a class derived from Screen, and accessing its static getter identifier:

export default function wrapStackNavigator<T extends typeof Screen>(screen:T){
    return <Stack.Navigator>
        <Stack.Screen name={screen.identifier} component={screen}/>
    </Stack.Navigator>
}

So far so good, I can call wrapStackNavigator with any screen classes with no type errors. Now the problem begins. I want to make my screens connected components, so I go ahead and connect them to Redux as usual:

export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(HomeScreen)

At this point, calls wrapStackNavigator starts complaining about types not being compatible. I know the reason: connect returns a different type which wraps the original class, but I have no idea how to fix it. I've tried to change wrapStackNavigator to accept ConnectedComponent or InferableComponentEnhancerWithProps (which apparently connect returns) but no avail (or I've got the type arguments wrong).

How can I make wrapStackNavigator accept either a class derived from Screen, or a connected class derived from Screen, while still being able to access static properties of the passed derived Screen class, with no typing errors? (and please, no casting to any, I know that would "solve" it but I don't consider it a solution). I'm on TypeScript 3.6.3.

How to integrate types defined in an external file in a React Typescript project

$
0
0

I have a Typescript based React Native project where i want to externalize - and thus reuse - type definitions like interface, enum etc in a file(or perhaps a few files within a directory).

My understanding is that this should work if i define a types or typings entry in my package.json. This doesn't seem to work as my IDE complains about not finding name when i attempt a simple Interface integration. I can of course import the required definitions in my files, but i thought that being an 'official' typescript project(using the template provided by @react-native-community) these should work out of the box.

My package.json:

{ 
  "name": "appname",
  "typings": "./src/typings/index.d.ts",
  ...
  "scripts": {
    ...
  },
  "dependencies": {
    ...
  },
  "devDependencies": {
    ...
    "@types/jest": "^24.0.18",
    "@types/react-native": "^0.60.22",
    ....
    "typescript": "^3.6.3"
  },
  ....
}

My tsconfig.json

{ 
  "compilerOptions": {    
    "resolveJsonModule": true,
    "target": "esnext",                      
    "module": "commonjs",                     
    "lib": ["es6"],                           
    "allowJs": true,                          
    "jsx": "react-native",                    
    "noEmit": true,                           
    "incremental": true,                      
    "isolatedModules": true,                  
    "strict": true,                           
    "moduleResolution": "node",               
    "baseUrl": "./",                          
    "allowSyntheticDefaultImports": true,    
    "esModuleInterop": true                  
  },
  "exclude": [
    "node_modules", "babel.config.js", "metro.config.js", "jest.config.js"
  ]
}

An example usage for a component:

export const ActionButton:React.FC<ActionButtonProps> =(props)=>{
...
}

where ActionButtonProps reads:

export enum EButtonType {
    primary= "PRIMARY", secondary= "SECONDARY", tertiary="TERTIARY"
}

export interface ActionButtonProps {
    title: string
    submitting: boolean
    onPress: ()=>void
    hideLoading?: boolean
    loadingSize?:number | "small" | "large" | undefined
    loadingColor?: string
    type?: keyof typeof EButtonType
}

I want to externalize the above in a separate file (defined in the typings property in package.json or something similar) and not have to import the required type definitions in each file i want to use it.

Currently my IDE complains with TS error 2304: 'Cannot find name ActionButtonProps' even though the file i have referenced in the typings property in package.json has the entries already defined.

I am assuming its just a case of missing some configuration or perhaps changing entries.

I tried the following, none of which works:

  • Have a triple-slash reference entry on top of the component file with a path attribute pointing to the file: /// <reference path="../../../../../typings/index.d.ts" />
  • Have a triple-slash reference entry on top of the component file with a path attribute pointing to a file that sits alongside: /// <reference path="./ActionButton.d.ts" />
  • Add an include property with wildcard values to tsconfig.json: "include": ["src/**/*","./src/typings/**/*"],
  • Add a typeRoots property with wildcard and non-wildcard values to tsconfig.json: "typeRoots": ["src/typings/", "src/typings/**/*"],

Any pointers would be greatly appreciated. If there is a solution, i have an additional pertinent query as well. Is there a way i could have the index.d.ts call separate files that reside in directories inside it? i.e src > typings > index.d.ts that calls entries defined in src > typings > moduleA > index.d.ts and src > typings > moduleB > index.d.ts

Edit

my TS version is 3.6.4 and node version is 12.12.0

How do we get nested object type in typescript

$
0
0

I have the following typescript interface:

UserInfo: {
     user: {
        options: ReadonlyArray<{
            values: ReadonlyArray<{
                value: string | null;
            }
        }
    }

I want to access the options how do I get it. I tried like below but it doesn't work for me

type options = ScreenQuery["UserInfo"]["user"]["options"];

How to access React child element props in a type safe manner with TypeScript?

$
0
0

I'm trying to access props of a React [Native] component in my app (which are guaranteed to be instance of element of my custom type ItemTemplate:

const children = React.Children.toArray(this.props.children);
return children.find(t => t.props.itemKey == key);

However, in the second line when I try to access t.props I'm getting:

Property 'props' does not exist on type 'ReactElement<ItemTemplate, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)> | ... 13 more ... | (ReactElement<...>[] & ReactPortal)'.
  Property 'props' does not exist on type 'ReactElement<ItemTemplate, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)>[] & string'.

The code does work correctly, but TypeScript (3.6.3) IntelliSense is complaining. Why?

React (Native) Architecture and state management

$
0
0

Trying to understand the best practice for React/React Native state. Coming from the Java world, I tend to follow MVC/MVVM in my applications, but reading about other approaches makes me wonder if I am designing my application properly.

Premise:

  • App mostly for consuming video and audio content, storing user statistics and progress
  • React Native Firebase from invertase.io
  • Redux used for storing data structure from Firebase Realtime Database

My current approach:

  • If a React Component needs data, it gets it via Redux or parent component via props.
  • If a component needs to manipulate/fetch more data, I have separate viewmodel classes (Typescript files with no dependency to React/RN) that are accessed in a component.
  • If the viewmodel gets new data from somewhere, the component state gets it via Observer pattern by implementing an interface
  • If data needs to be persisted to Redux and/or Firebase, the viewmodel does it. I pass the Store object from the component

Approach I read/heard/discussed:

  • All data from/to components is received/sent through Redux
  • All data manipulations are done in Redux Actions
  • No separate controllers/viewmodels

I don't have too much history with React Native, so I am trying to understand whether the latter approach is actually superior for some reason.

Type issue in Typescript React-native styled-component

$
0
0

I am trying to create a TouchableOpacity using styled-component in react-native and was working successfully but since i am using typescript its showing some error when using style flowDirection: 'row'

here is my code

interface IDefaultStyle {
  style?: object
}

const RootContainer = styled.TouchableOpacity((props: IDefaultStyle) => ({
  flexDirection: 'row',
  ...props.style
}))

And the type error is

Argument of type '(props: IDefaultStyle) => { flexDirection: string; } | { flexDirection: string; }' is not assignable to parameter of type 'TemplateStringsArray'.

Type Error

And when i remove flexDirection and add any other style type. the error is gone.

The same issue is seen in styled-components Text when fontWeight: 'bold' is given

My package.json

{
  "name": "@appmaker/ui",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "peerDependencies": {
    "react": "16.9.0",
    "react-native": "0.61.2"
  },
  "devDependencies": {
    "@babel/core": "7.6.4",
    "@babel/preset-typescript": "^7.7.2",
    "@babel/runtime": "7.6.3",
    "@react-native-community/eslint-config": "0.0.3",
    "@types/jest": "^24.0.20",
    "@types/react": "^16.9.11",
    "@types/react-native": "^0.60.22",
    "@types/react-test-renderer": "^16.9.1",
    "@types/styled-components": "^4.1.20",
    "@typescript-eslint/eslint-plugin": "^2.5.0",
    "@typescript-eslint/parser": "^2.5.0",
    "babel-jest": "24.9.0",
    "babel-plugin-styled-components": "^1.10.6",
    "jest": "24.9.0",
    "metro-react-native-babel-preset": "0.51.1",
    "prettier": "^1.18.2",
    "react-test-renderer": "16.9.0",
    "tslint": "^5.20.0",
    "tslint-config-prettier": "^1.18.0",
    "tslint-config-standard": "^8.0.1",
    "tslint-eslint-rules": "^5.4.0",
    "tslint-react": "^4.1.0",
    "typescript": "^3.6.3",
    "typescript-plugin-styled-components": "^1.4.3"
  },
  "jest": {
    "preset": "react-native",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "jsx",
      "json",
      "node"
    ]
  },
  "bit": {
    "env": {
      "compiler": "bit.envs/compilers/react-typescript@3.0.27"
    },
    "componentsDefaultDirectory": "components/{name}",
    "packageManager": "npm"
  },
  "dependencies": {
    "i": "^0.3.6",
    "npm": "^6.12.0",
    "prop-types": "^15.7.2",
    "react-native-image-slider": "^2.0.3",
    "react-native-image-slider-box": "^1.0.5",
    "react-native-snap-carousel": "^3.8.3",
    "styled-components": "^4.4.0"
  }
}

it will be greatly appreciated if someone could help me with this

Edit component usage

/**
 * ## AuthorView  | SellerView
 * Component to show Author info
 * @param props
 */
const AuthorView = (props: IProps) => {

  const { name, style, imageUrl, rating, subtext, onPress } = props

  // if imageUrl is not provided use default star icon
  const imageSource = imageUrl ? { uri: imageUrl } : require('../../icons/star-grey.png')

  return(
    <RootContainer onPress={onPress} style={style}>
        <ImageViewContainer>
            <ImageView
              defaultImage={imageUrl ? false : true}
              source={ imageSource }
            />
        </ImageViewContainer>
        <RightContainer>
            <Name>{name}</Name>
            <View style={{ flexDirection: 'row' }}>
            {rating && <RatingView style={{ marginRight: 3 }} rating={rating} />}
            <SubText>{subtext}</SubText>
            </View>
        </RightContainer>
    </RootContainer>
  )
}

export default AuthorView

ForwardRef on a custom component typescript

$
0
0

I'm trying to access a children component function from his parent using references.

I've my parent component :

const Parent: FC = (props) => {
    let childRef = useRef(null);

    const handle = () => {
        childRef.current.customFunction();
    }

    return (
        <Children props1="value" ref={childRef}/>
        <Button onPress={handle}/>
}

And my children component :

interface Props {
    props1: string
}

const Children: FC<Props> = forwardRef((props,ref) => {
    const customFunction = () => {
        console.log("Custom");    
    }

    return <View>props.children</View>
})

I have a typescript error when rendering my children component :

Property 'ref' does not exist on type 'intrinsicAttribute & props & {children?:ReactNode}

Note that I would like to keep any strict type.

Text Color not changing in React Native

$
0
0

So I'm messing with React Native using Typescript, im trying to implement a dark mode system (once I have it working it will be going into Redux State) however, My Background is changing colour but my text is not.

I have seen React Native Text color not working my state is updating because my background colour is changing.

import React from 'react';
import { StyleSheet, Text, StatusBar, SafeAreaView, AsyncStorage, Button } from 'react-native';

export interface Props{
  name: string;
}

export interface State{
  darkmode: boolean;
  ready:boolean;
}

export interface DarkModeStyle{
  backgroundColor: string;
  color: string
}

export interface LightModeStyle{
  backgroundColor: string;
  color: string
}

export default class BeaconAppFrame extends React.Component<Props, State>{
  private styles;

  public state : State = {
    darkmode:false,
    ready:false
  }

  public darkModeStyle : DarkModeStyle = {
    backgroundColor:"#555", 
    color:"#EEE"
  }

  public lightModeStyle : LightModeStyle = {
    backgroundColor:"#FFF",
    color:"#000"
  }

  constructor(props: Props){
    super(props);

    // setup the default frame styles
    this.styles = StyleSheet.create({
      container: {
        flex: 1,
        alignItems: 'flex-start',
        justifyContent: 'flex-start',
      }
    });
  }

  componentDidMount(){
    AsyncStorage.getItem('darkmode').then( (darkmode) => {
      this.setState({darkmode:darkmode === "yes", ready:true});
    }).catch(() => {
      this.setState({darkmode:false, ready:true});
      AsyncStorage.setItem("darkmode", "no");
    });
  }

  enableDarkMode(){
    this.setState({"darkmode":!this.state.darkmode});
    AsyncStorage.setItem("darkmode", this.state.darkmode?"yes":"no");
  }

  render(){
    if(this.state.ready){
      let style = [this.styles.container, this.state.darkmode?this.darkModeStyle:this.lightModeStyle];
      console.log(style);
      return (
        <SafeAreaView style={style}>
          <StatusBar barStyle="light-content" hidden={true} translucent={false} />
          <Text>darkmode is set to {this.state.darkmode? "Active":"Inactive"}</Text>
          <Button onPress={this.enableDarkMode.bind(this)} title={"Toggle darkmode"}>
            <Text>Toggle Darkmode</Text>
          </Button>
        </SafeAreaView>
      );
    }else{
      return (
        <SafeAreaView style={this.styles.container}>
            <Text>Please Wait Loading</Text>
        </SafeAreaView>
      )
    }
  }
}

React Native stylesheet merge: Spread types may only be created from object types

$
0
0

I'm trying to merge an existing style with my extra styling in React Native's regular StyleSheet.create method:

const styles = StyleSheet.create({
    blurView:{
        ...StyleSheet.absoluteFill,
        borderRadius: 24
    },

});

However I'm getting the following error on line ...StyleSheet.absoluteFill:

Spread types may only be created from object types.

What am I doing wrong? I know I can pass an array into style prop, but I'm just curious why this isn't working.

Javascript: Unexpected token { - occurs when try to import custom class in typescript file into javascript file

$
0
0

I am writing simple CLI scripts for react-native project. But I am not available to import class from typescript to javascript. It throw me following error.

import { TestResult } from './src/lib/modules/test-result';
SyntaxError: Unexpected token {...

package.json

...
"script": {
...
"formular:convert": "node convertor.js"
...
}
...

convertor.js

import {TestResult} from './src/lib/models/test-result';
...

test-result.ts

import uuid from 'uuid/v4';

import { Exception } from '../../errors';
import { OilTypes, RawMaterialTypes } from '../oils';

import { CalculatedResult } from './calculated-result';
import { DeviceSettings } from './device-settings';
import { DeviceStatus } from './device-status';
import { DisplayedResult } from './displayed-result';
import { Measurement } from './measurement';
import { PhoneInfo } from './phone-info';
import { PrimaryCompound } from './primary-compound';

export class TestResult {
    constructor(
        public id: string = uuid(),
        public createdAt: Date = new Date(),
        public updatedAt: Date = new Date(),
        public errors: Exception[] = [],
        public alias: string = '',
        public analyteTemp: number = 75,
        public flowerWeight: number = 0,
        public hidden: boolean = false,
        public note: string = '',
        public oilType: OilTypes = OilTypes.OliveOil,
        public primaryCompound: PrimaryCompound = PrimaryCompound.UNDEFINED,
        public units: string = '',
        public user: string = '',
        public air310Meas: Measurement = new Measurement(),
        public air280Meas: Measurement = new Measurement(),
        public analyte310Meas: Measurement = new Measurement(),
        public analyte280Meas: Measurement = new Measurement(),
        public calculated: CalculatedResult = new CalculatedResult(),
        public displayed: DisplayedResult = new DisplayedResult(),
        public status: DeviceStatus = new DeviceStatus(),
        public settings: DeviceSettings = new DeviceSettings(),
        public phoneInfo: PhoneInfo = new PhoneInfo(),
        public rawMaterialType: RawMaterialTypes = RawMaterialTypes.Isolate,
    ) {
    }
}

tsconfig.json

{
    "compilerOptions": {
        /* Basic Options */
        "target": "es5",                       /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
        "module": "commonjs",                  /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
        // "lib": [],                             /* Specify library files to be included in the compilation. */
        "allowJs": true,                       /* Allow javascript files to be compiled. */
//        "checkJs": true,                       /* Report errors in .js files. */
        "jsx": "react",                 /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
                            /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
        "removeComments": true,                /* Do not emit comments to output. */
        "noEmit": true,                        /* Do not emit outputs. */


        /* Strict Type-Checking Options */
        "strict": true,                        /* Enable all strict type-checking options. */

        /* Additional Checks */
        "noUnusedLocals": true,                /* Report errors on unused locals. */
        "noUnusedParameters": true,            /* Report errors on unused parameters. */
        "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
        "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

        /* Module Resolution Options */
        "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
        "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
        "types": [                             /* Type declaration files to be included in compilation. */
            "jest",
            "mocha",
            "detox"
        ],
        "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
        "esModuleInterop": true,               /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */

        /* Experimental Options */
        "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
        "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
        "skipLibCheck": true,                  /* Skip type checking of declaration files. Requires TypeScript version 2.0 or later. */
        "forceConsistentCasingInFileNames": true,/* Disallow inconsistently-cased references to the same file. */
        "resolveJsonModule": true              /* Include modules imported with '.json' extension. Requires TypeScript version 2.9 or later. */
    },
    "exclude": [
        "node_modules",
        "babel.config.js",
        "metro.config.js",
        "jest.config.js"
    ]
}

I stuggled to find the solution, and found some answers here and there, but all of them doesn't work.

Thanks for your help.


The most important aspects when transitioning from React Native to Flutter

$
0
0

Before starting a project, I always want to figure out the best ways to organize the project - the most important concepts are: How to structure modules/components, ... , and which suitable patterns should be use in

In React Native, the project structure, with Redux pattern, be often formed as:

 - /src
    - types
    - constants
    - components
        - collection
        - todolist
        - settings
        - etc ...
    - utils
    - reducers
    - store.ts
    - middleware.ts
    - rootReducer.ts

But when transitioning from React Native to Flutter, the concepts of project structure/pattern is so different.

It seem that all our source files should be located under /lib .

So, currently I've been facing with project structure to organize my modules/components/ ..., and the best UI pattern should be used in.

Could you please give me some ideas as detailed as possible?

Delete a key from a copy of Map object

$
0
0

I'm trying to delete a key of my react-native state Map object.

const [errors, setErrors] = useState<Map<string, string>>(null);
let copy: Map<string,string> = {...errors}
copy["a"] = "a";
setErrors(copy);
let copy2: Map<string,string> = {...errors};
copy2.delete("a"); //Got error here
setErrors(copy2);

But i've this error :

copy2.delete is not a function (In 'copy2.delete("a"),'copy2.delete' is undefined)

How to handle that ?

How to get value of AnimatedInterpolation

$
0
0

My question is how to retrieve the value of an AnimatedInterpolation in react-native, without calling private code.

I create the animated value and wrap it in an interpolation like this:

  animated = new Animated.Value();
  interpolated = this.animated.interpolate({
    inputRange:[0, 1000],
    outputRange:[0, 500]
  })

I render the animation like this:

<Animated.View style={[{width: this.interpolated}]}/>

And I retrieve the animated value like this:

  this.animated.stopAnimation(v => {
    console.log(v, "", this.interpolated.__getValue());
  })

Runnable example here.

My problem is that __getValue() is a private member of AnimatedInterpolation and it gives an error when using typescript. I'm looking for a sound way to retrieve the value, similarly to how this.animated.stopAnimation is sounder than this.animated.__getValue().

Error: [class] is not a constructor when importing npm module in react-native application

$
0
0

I'm writing react-native application and using npm module @waves/signature-adapter. When I make import { Seed } from '@waves/signature-generator'; compiler returns an error undefined is not a constructor (evaluating 'new __1.Base58('senderPublicKey')'). At first I thought the way I imported the lib was wrong but then I tried to do the same for new react application (not react-native) and it is imported and works with no errors. The module is written in typescript but I'm not sure it really matters cause my app uses lots of other modules written in typescript. I try to understand what's wrong cause I have same-same code in both apps, but it gives the error in react-native.

how to create state array react hooks on declaration

$
0
0

How do I create a state array with react hooks? I am passing a Type I used this method but it's showing me lint error. I also want to know it's the correct method

const [myList, setList] = React.useState<IList[]>([
  {
    ID: 1,
    Lname: "R1",
    LType: 1
  },
  {
    ID: 2,
    Lname: "R4",
    LType: 5
  }
]);

And my type looks like

interface IList {
  ID: number;
  Lname: string;
  LType: number;
}
Viewing all 6406 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>