Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript support #219

Open
yayajacky opened this issue Jan 23, 2019 · 5 comments
Open

Typescript support #219

yayajacky opened this issue Jan 23, 2019 · 5 comments

Comments

@yayajacky
Copy link

This is great for getting script to be injected at the beginning of page load. Could we get a @types/react-native-wkwebview package? That would make it very usable with typescript based projects.

Thanks!

@shirakaba
Copy link
Collaborator

That does sound like a nice idea. I'd recommend bundling the types with the project rather than splitting it out into @types, however.

I'll note that I use the regular WebView types and a sprinkling of //@ts-ignore when developing with this in TypeScript.

@shauns
Copy link

shauns commented Feb 20, 2019

Would you be able to share what you do? Presumably you have a baseline declare module somewhere?

@shirakaba
Copy link
Collaborator

shirakaba commented Feb 24, 2019

@shauns Here's how I do it:

import React, {Component} from 'react';
import {NavState, WebView, WebViewIOSLoadRequestEvent} from 'react-native';
import WKWebView from 'react-native-wkwebview-reborn';
import {toggleButtonStateRequest, WebViewActionCreators} from "../store/actions/webView";


declare module "react-native" {
    interface WebView {
        evaluateJavaScript(script: string): Promise<string>
    }
}

interface Props {
    onNavigationStateChange(navState: NavState);
}
// Combine with Redux props. I've omitted StateMappedToProps and DispatchMappedToProps for brevity.
type ConnectedProps = Props & StateMappedToProps & DispatchMappedToProps;

interface State {
}

export class MainWebView extends Component<ConnectedProps, State> {
    private webView: WebView|null = null;

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

        this.state = {
        };
    }

    render() {
        // This comes from Redux.
        const {
            webView,
            onNavigationStateChange
        } = this.props;

        return (
            <WKWebView
                ref={(wv: WKWebView) => { this.webView = wv; }}
                automaticallyAdjustContentInsets={false}
                style={{
                    // I'm omitting these for brevity.
                }}
                source={{ uri: webView.navState.url }}
                injectJavaScriptForMainFrameOnly={false}
                onMessage={(ev: WKWebViewMessageEvent) => {}}
                injectedJavaScript={ "/* script goes here */"}
                onError={(error: NavState) => console.error(error)}
                // mixedContentMode={"always"} // Android-only
                // javaScriptEnabled={true} // Android-only
                domStorageEnabled={true}
                decelerationRate="normal"
                onNavigationStateChange={(navState: NavState) => {
                    onNavigationStateChange(navState);
                }}
                onShouldStartLoadWithRequest={
                    (event: WebViewIOSLoadRequestEvent & { navigationType: WKNavigationType }) =>
                    {}
                }
                startInLoadingState={false}
                scalesPageToFit={true}
            />
        );
    }
}

And here's my tsconfig.json:

{
  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "jsx": "react-native",
    "lib": [
        "ES5", "ScriptHost", "ES2015.Collection", // Standard ES5 libs
        "es2015.iterable" // for redux-saga
    ],
    "baseUrl": ".",
    "noEmit": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true
  },
  "exclude": [
      "node_modules",
      "**/*.spec.ts",
      "assets"
  ]
}

When developing, in practice, I refer initially to the React Native core's WKWebView typings and just adjust from there as necessary. It looks like I don't get any intellisense when writing my JSX. I don't have a .d.ts file for the module, so I'm surprised that there's no TypeScript error on the import (it's probably due to running in non-strict mode). As the import lacks any typings, the whole module is simply assumed to be of any type. I don't think it's doing any inference from WKWebView.ios.js, but there may be a tsconfig.json option for that.

@shauns
Copy link

shauns commented Feb 25, 2019

Thank you @shirakaba ! FWIW here's what we ended up doing at our end. We do get Intellisense with this approach, but it lacks full feature set etc. -- just the extensions to the default we ended up using.

declare module "react-native-wkwebview-reborn" {
  import { WebView } from "react-native";
  import { Component } from "react";

  type Props = WebView["props"] & {
    allowsBackForwardNavigationGestures: boolean;
  };

  export default class WkWebView extends Component<Props> {
    stopLoading(): void;
  }
}

@insraq
Copy link
Contributor

insraq commented Mar 1, 2019

You can certainly use roll your own d.ts. It is unlikely that this project will be rewritten in TypeScript. You are more than welcome to open a PR and contribute your d.ts file!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants