Giter Club home page Giter Club logo

webview-bridge's Introduction

webview-bridge

NPM NPM NPM NPM

Fully Type-Safe Integration for React Native WebView and Web

webview-bridge is a powerful interface that acts as a bridge between React Native and web applications using react-native-webview. It providing seamless interaction and ensuring type safety.

Inspired by the functionality of tRPC, webview-bridge simplifies the communication process between react-native-webview and web applications.

Key Features:

  • Built upon react-native-webview.
  • Designed with zero external dependencies (except for react-native-webview).
  • Type-Safety
  • Backward Compatibility
  • No App Review Needed
  • Shared State

webview-bridge

Documentation

visit Docs

Example

visit Example

Exporting Type Declarations

To enhance your experience with webview-bridge, it's recommended to export the type declaration of the native bridge object to the web application. Here are a few ways to achieve this:

  1. Monorepo Setup (Recommended): Use a monorepo setup to export the type of the native bridge.
  2. Custom Declaration File: Build a bridge declaration file using tsc and move the file as needed.
  3. Private npm Registry: Utilize a private npm registry to export the type of the native bridge.

Contributor Guide

If you would like to contribute to webview-bridge by submitting bug fixes or performance improvements, please refer to our CONTRIBUTING.md guide for detailed instructions. We welcome and appreciate your contributions.

webview-bridge's People

Contributors

doyoonkim12345 avatar gronxb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

webview-bridge's Issues

what is the best practice to call hooks in react native from hooks

hi !

iam a fan of this project.

now i am using this project into my company's main project.

i think this project has a potential power.

I Love it.

I want to call a hook from web to rn web by this package.

i want to know what is the best practice

Can you explain Some?

i hope many people love this project

Throw Timeout Error

If a webMethod throw a Error, and then you will get a Timeout Error.

/// WebMethod Define
async test() {
  throw new Error('test error');
}

/// App Invoke WebMethod
webMethod.current.test().catch(e => console.warn(e)); // then you will get a timeout error but not the "test error"

Feature: bridge isReady event or callback

A common scene is that:

When web page ready, app inject some data into web. Otherwise, app should prepare some async environment when web already done. For example lazy load modules in app, loading process will cost times.

Suggestion API Design:

  • ready state getter, maybe current field 'isReady'
  • ready state change event, maybe provide as subscription or event emitter.

web에서 타입 문제

우선 한국어가 가능하신 듯 하여 한국어로 질문드립니다.
If you are not familiar with Korean, please let me know. I will register the issue again in English.

안녕하세요 최근에 새로은 프로젝트를 시작하면서 해당 라이브러리를 사용해보려하고 있습니다. (1.4.1 최신버전을 사용하려 했습니다.)

그런데 동작은 잘 되지만 사용할 때 제대로 타입 추론이 안돼서 질문드립니다.

  1. linkBridge 타입 추론
image a. 우선 공식문서에 나온대로 설정을 완료했으나 타입이 제대로 추론안되는지 사진과 같은 error가 나옵니다.

b. 추론되는 타입도 AppBridge에서 추론된 타입이 메서드로 등록돼야할 것 같은데, AppBridge의 return type도 BridgeStore로 연결되는 듯 해서 혹 이부분에 대해 제가 어떻게 해보면 좋을 지 의견 구합니다!

  1. useBridgeStore 타입 추론
image a. 이 메서드도 마찬가지로 error가 등장합니다. 이 친구는 제네릭 때문인 것 같긴한데 혹 해결할 방법있을까요?

감사합니다!

Not Working with after update from CodePush

The Functions and data passed from the bridge is inaccessible after a release has been made via OTA using CodePush

packages

 "@webview-bridge/react-native": "^1.3.3",
"react-native-code-push": "^8.2.1", 
 "react": "18.2.0",
 "react-native": "0.71.12",

import {bridge} from '@webview-bridge/react-native';
import {RootStackParamList} from '../../types/RootStackPrams';
import {
  StackActions,
  createNavigationContainerRef,
} from '@react-navigation/native';
import {goBack, navigate} from '@utils/NavigationService';
import {store} from '@config/configureStore';
import {hbookAPI} from '@utils/ApiUtils';

export const navigationRef = createNavigationContainerRef<RootStackParamList>();

export const appBridge = bridge({
  async canGoBack() {
    return await Boolean(
      navigationRef.current?.isReady() && navigationRef.current.canGoBack(),
    );
  },
  async goBack() {
    await goBack();
  },
  async navigate<RouteName extends keyof RootStackParamList>(
    name: RouteName,
    params: RootStackParamList[RouteName],
  ) {
    if (name === 'ChatSettingScreen') {
      params = {...params, screenName: 'ChatScreen'};
    }
    await navigate(name as any, params as any);
  },
  async push<RouteName extends keyof RootStackParamList>(
    name: RouteName,
    params: RootStackParamList[RouteName],
  ) {
    if (navigationRef.current?.isReady()) {
      await navigationRef.current.dispatch(StackActions.push(name, params));
    }
  },
  async replace<RouteName extends keyof RootStackParamList>(
    name: RouteName,
    params: RootStackParamList[RouteName],
  ) {
    if (navigationRef.current?.isReady()) {
      await navigationRef.current.dispatch(StackActions.replace(name, params));
    }
  },
  async popToTop() {
    if (navigationRef.current?.isReady()) {
      await navigationRef.current.dispatch(StackActions.popToTop());
    }
  },
  async getNativeState() {
    return await store.getState();
  },
  async changeBranch(token, id) {
    try {
      const response = await hbookAPI().post(
        'api/get-token',
        {
          data: {
            token,
            id,
          },
        },
      );
      return response.data;
    } catch (error) {
      console.error(error);
    }
  },
});

export type AppBridge = typeof appBridge;

Next.js side

packages

 "@webview-bridge/react": "^1.4.0",
 "@webview-bridge/web": "^1.4.0",
  "next": "14.1.1",
  "react": "^18",
"use client";
import { createLinkBridgeProvider } from "@webview-bridge/react";

export const {
  BridgeProvider,
  useBridgeStore,
  useBridgeStatus,
  useBridgeLoose,
} = createLinkBridgeProvider({
  throwOnError: true,
  onReady: () => {
    console.log("Bridge is ready");
  },
});
import { useCallback, useEffect, useState } from "react";
import { useBridgeStatus, useBridgeStore } from "@/providers/BridgeProvider";

interface NativeState {
  loginMobileReducer: {
    token: string;
    book_token: string;
    doctor_role_id: string;
    doctor_details: {
      doctor_id: string;
      doctor_name: string;
      doctor_profile_image: string;
      branch_doctor_id: string;
      branch_name: string;
      patient_role_id: string;
    };
  };
}

const useNativeBridge = () => {
  const [nativeState, setNativeState] = useState<NativeState>();

  const { getNativeState, goBack, canGoBack, navigate, changeBranch } =
    useBridgeStore((state) => ({
      getNativeState: state.getNativeState,
      goBack: state.goBack,
      canGoBack: state.canGoBack,
      navigate: state.navigate,
      changeBranch: state.changeBranch,
    }));

  const { isNativeMethodAvailable, isWebViewBridgeAvailable } =
    useBridgeStatus();

  const isNativeMethodSafe = useCallback(
    (method: string | number) =>
      isWebViewBridgeAvailable && isNativeMethodAvailable(method),
    [isWebViewBridgeAvailable, isNativeMethodAvailable]
  );

  const fetchNativeState = useCallback(async () => {
    if (!isNativeMethodSafe("getNativeState")) return;
    const state = await getNativeState();
    setNativeState(state);
  }, [getNativeState, isNativeMethodSafe]);

  const fetchNativeGoBack = useCallback(async () => {
    if (!isNativeMethodSafe("goBack")) return;
    return await goBack();
  }, [goBack, isNativeMethodSafe]);

  const fetchNativeCanGoBack = useCallback(async () => {
    if (!isNativeMethodSafe("canGoBack")) return;
    return await canGoBack();
  }, [canGoBack, isNativeMethodSafe]);

  const fetchNativeNavigate = useCallback(
    async (screenName: string) => {
      if (!isNativeMethodSafe("navigate")) return;
      return await navigate(screenName);
    },
    [navigate, isNativeMethodSafe]
  );

  const switchBranchSPOT = useCallback(
    async (token: string, id: string) => {
      if (!isNativeMethodSafe("changeBranch")) return;
      return await changeBranch(token, id);
    },
    [changeBranch, isNativeMethodSafe]
  );

  useEffect(() => {
    fetchNativeState();
  }, [fetchNativeState]);

  return {
    nativeState,
    isNativeMethodSafe,
    isWebViewBridgeAvailable,
    fetchNativeGoBack,
    fetchNativeCanGoBack,
    fetchNativeNavigate,
    switchBranchSPOT,
  };
};

export default useNativeBridge;

CRA project import Error

Init a create-react-app, and import @webview-bridge/web,will get this error!

Module not found: Default condition should be last one

1 | import { linkNativeMethod, registerWebMethod } from '@webview-bridge/web';

Feature: Shared State with react native and react

for example. App inject the token, userInfo, business id, business info, web get the state; and web can change it, app will auto useEffect the change of any state.

It's a common usecase for every webview hybrid app.

Bridge object is always empty.

Printing bridge object always comes out as empty object and cannot access methods by passing the bridge around. Followed the setup given in the docs. Not sure what's going wrong. However, I am able to access the methods by using the useBridge hook.

API design recommendation: web and native API definitions should be in the same file.

I suggest that for most scenarios, where RN (React Native) and Web projects are not organized as a monorepo, exporting TypeScript (TS) files can be a suitable approach to keep the two projects in sync. However, the interaction between the two sides is usually intertwined. By merging them together, we can simplify the process and reduce the cognitive burden of distinguishing which side's interface is being used.

Furthermore, as we move forward, adding functionalities like subscription channels and error handling should also be defined in the same file. This approach minimizes maintenance costs and enhances scalability, as code bundling is the responsibility of the bundler, and our focus should be on maintainability.

Therefore, my suggestion is to adopt a methodology where both APIs are consistently declared in the same file, without the need for exporting TS files by some scripts.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.