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

Request to Node 0 failed due to "undefined Network Error" | Error: Exception in HostFunction: Malformed calls from JS: field sizes are different. #189

Open
walter-ayala opened this issue Dec 20, 2023 · 3 comments

Comments

@walter-ayala
Copy link

walter-ayala commented Dec 20, 2023

Description

I'm using TypesenseInstantSearchAdapter from 'typesense-instantsearch-adapter' and InstantSearch, useInfiniteHits, useSearchBox from 'react-instantsearch-core' in my react native app, when i run the app for ios that part works, but in android don't working

Information about it

image image

That is my dependencies in my package.json

"dependencies": {
    "@apollo/client": "^3.8.4",
    "@react-native-async-storage/async-storage": "^1.19.3",
    "@react-native-firebase/app": "^18.5.0",
    "@react-native-firebase/auth": "^18.5.0",
    "@react-native-firebase/messaging": "^18.5.0",
    "@react-native-masked-view/masked-view": "^0.2.9",
    "@react-navigation/bottom-tabs": "^6.2.0",
    "@react-navigation/native": "^6.1.8",
    "@react-navigation/native-stack": "^6.9.14",
    "@reduxjs/toolkit": "^1.9.6",
    "@sentry/cli": "^2.22.3",
    "@sentry/react-native": "^5.14.1",
    "i18next": "^23.5.1",
    "mixpanel-react-native": "^2.2.5",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-fast-compare": "^3.2.2",
    "react-i18next": "^13.2.2",
    "react-instantsearch-core": "^7.3.0",
    "react-instantsearch-hooks": "^6.47.3",
    "react-native": "^0.72.7",
    "react-native-autocomplete-dropdown": "^3.1.0",
    "react-native-bootsplash": "^5.1.3",
    "react-native-bouncy-checkbox": "^3.0.7",
    "react-native-config": "^1.5.1",
    "react-native-countdown-circle-timer": "^3.2.1",
    "react-native-date-picker": "^4.2.6",
    "react-native-device-info": "^10.12.0",
    "react-native-geolocation-service": "^5.3.0-beta.4",
    "react-native-gesture-handler": "^2.13.1",
    "react-native-image-picker": "^5.6.1",
    "react-native-image-slider-box": "megamaxs1234/react-native-image-slider-box",
    "react-native-indicators": "^0.17.0",
    "react-native-keyboard-aware-scroll-view": "^0.9.5",
    "react-native-linear-gradient": "^2.8.3",
    "react-native-maps": "^1.7.1",
    "react-native-mask-input": "^1.2.3",
    "react-native-modalize": "^2.0.13",
    "react-native-pdf": "^6.7.1",
    "react-native-portalize": "^1.0.7",
    "react-native-progress": "^5.0.0",
    "react-native-ratings": "^8.1.0",
    "react-native-reanimated": "^3.6.1",
    "react-native-reanimated-carousel": "^3.1.0",
    "react-native-safe-area-context": "^4.7.2",
    "react-native-screens": "^3.25.0",
    "react-native-share": "^9.4.1",
    "react-native-skeleton-placeholder": "^5.0.0",
    "react-native-star-rating-widget": "^1.2.0",
    "react-native-toast-message": "^2.1.8",
    "react-native-uuid": "^2.0.1",
    "react-native-webview": "^13.5.0",
    "react-native-youtube-iframe": "^2.3.0",
    "react-redux": "^8.1.3",
    "redux": "^4.2.1",
    "redux-persist": "^6.0.0",
    "tslib": "^2.3.0",
    "typesense-instantsearch-adapter": "^2.7.1"
  },
@jasonbosco
Copy link
Member

Could you share your TypesenseInstantSearchAdapter initialization code?

@walter-ayala
Copy link
Author

walter-ayala commented Dec 20, 2023

Could you share your TypesenseInstantSearchAdapter initialization code?

That's my custom hook:

import Config from 'react-native-config';
import TypesenseInstantSearchAdapter from 'typesense-instantsearch-adapter';

export const useSearchVehicle = () => {
 const typesenseInstantsearchAdapter = useMemo(() => {
    return new TypesenseInstantSearchAdapter({
      server: {
        nodes: [
          {
            host: Config.TYPESENSE_HOST,  // For Typesense Cloud use xxx.a1.typesense.net
            port: 8108, // For Typesense Cloud use 443
            protocol: 'http', // For Typesense Cloud use https
          },
        ],
        apiKey: Config.TYPESENSE_API_KEY,
        connectionTimeoutSeconds: 500,
      },
      // The following parameters are directly passed to Typesense's search API endpoint.
      //  So you can pass any parameters supported by the search endpoint below.
      //  query_by is required.
      additionalSearchParameters: {
        sort_by: 'typeRecord:asc',
        query_by: 'brandName,modelName',
        filter_by: 'typeRecord:=MODEL',
      },
    });
  }, [Config])
  
  const searchClient = typesenseInstantsearchAdapter.searchClient;

  return {searchClient}
};

And that is my component to search and show the hits:

/* eslint-disable react/no-unstable-nested-components */
import React, {useEffect, useRef, useState} from 'react';
import {
  FlatList,
  Image,
  Keyboard,
  TouchableOpacity,
  View,
} from 'react-native';
import {Portal} from 'react-native-portalize';
import {Modalize} from 'react-native-modalize';
import Text from "../../../common/components/Text/Text";
import Input from '../../../common/components/Inputs/Input';
import {t} from 'i18next';
import {IModelCarModal} from '../../../vehicles/models/model';
import {IconSearch} from '../../../common/components/Icons/IconSearch';
import {height, resize} from '../../../common/styles/helpers';
import {COLORS} from '../../../common/styles/constants/colors';
import emptyResult from '../../assets/EmptyResult.png';
import style from '../styles';
import {IconRightArrow} from '../../../common/components/Icons/IconRigthArrow';
import useMixpanel from '../../../common/hooks/useMixpanel';
import useMixpanel from '../../../common/hooks/useSearchVehicle';
import {
  InstantSearch,
  useInfiniteHits,
  useSearchBox,
} from 'react-instantsearch-core';
import Config from 'react-native-config';

const SearchVehicleModal: React.FC<IModelCarModal> = props => {
  const modalizeRef = useRef<Modalize>(null);
  const currentStyle = style();
  const [keyboardOffset, setKeyboardOffset] = useState(0);
  const [timer, setTimer] = useState<NodeJS.Timeout | null>(null);
  const {searchClient}=useSearchVehicle();

  const onOpen = () => {
    modalizeRef.current?.open();
  };

  useEffect(() => {
    setTimeout(() => {
      if (modalizeRef.current) {
        onOpen();
      }
    }, 200);
  }, [modalizeRef.current]);

  useEffect(() => {
    return () => {
      if (timer) {
        clearTimeout(timer);
      }
    };
  }, [timer]);

  const {track} = useMixpanel();

  useEffect(() => {
    const showSubscription = Keyboard.addListener(
      'keyboardDidShow',
      onKeyboardShow,
    );
    const hideSubscription = Keyboard.addListener(
      'keyboardDidHide',
      onKeyboardHide,
    );

    return () => {
      showSubscription.remove();
      hideSubscription.remove();
    };
  }, []);

  const onKeyboardShow = event => {
    if (props.carModel.trim() == '') {
      setKeyboardOffset(event.endCoordinates.height);
    }
  };

  const onKeyboardHide = () => {
    setKeyboardOffset(0);
  };

  const handleInputChange = (model: string) => {
    props.onChange(model);

    if (timer) {
      clearTimeout(timer);
    }

    const newTimer = setTimeout(() => {
      track('Input Value Entered', {value: model});
    }, 2000);

    setTimer(newTimer);
  };

  return (
    <Portal>
      <InstantSearch
        searchClient={searchClient}
        future={{ preserveSharedStateOnUnmount: false }}
        indexName={Config.TYPESENSE_INDEX_NAME}>
        <Modalize
          ref={modalizeRef}
          // panGestureEnabled={props.carModel.trim() !== ''}
          // alwaysOpen={125}
          panGestureEnabled={false}
          adjustToContentHeight
          withOverlay={false}
          // alwaysOpen={props.carModel.trim() !== '' ? height / 1.1 : 125}
          handlePosition="inside"
          closeOnOverlayTap={false}
          modalStyle={[
            {
              borderWidth: resize(1),
              borderTopStartRadius: resize(24),
              borderTopEndRadius: resize(24),
              borderColor: COLORS.GREY,
            },
            // Platform.OS === 'ios' && {
            //   bottom: props.carModel.trim() !== '' ? keyboardOffset : undefined,
            // },
          ]}
          FooterComponent={() => {
            if (props.carModel.trim() === '') {
              return null;
            }

            return (
              <TouchableOpacity
                onPress={props.onAddManually}
                style={currentStyle.footerModalContainer}>
                <Text style={currentStyle.footerButtonModal}>
                  {t('add_car:model_car_modal:add_manually')}
                </Text>
              </TouchableOpacity>
            );
          }}
          HeaderComponent={<SearchBox handleInput={handleInputChange} />}
          >
          {props.carModel.trim() !== '' ? (
            <InfiniteHits
              onPress={props.onPress}
              isKeyboardShow={keyboardOffset !== 0}
            />
          ) : null}
        </Modalize>
      </InstantSearch>
    </Portal>
  );
};

function InfiniteHits({...props}) {
  const {hits, isLastPage, showMore} = useInfiniteHits();
  const currentStyle = style();

  return (
    <FlatList
      data={hits}
      style={{height: props.isKeyboardShow ? height / 4 : height / 1.6}}
      keyExtractor={item => item.objectID}
      onEndReached={() => {
        if (!isLastPage) {
          showMore();
        }
      }}
      ListHeaderComponent={
        <>
          {hits.length !== 0 && (
            <Text style={currentStyle.subtitleModal}>
              {t('add_car:model_car_modal:results')}
            </Text>
          )}
        </>
      }
      ListEmptyComponent={
        <View style={currentStyle.emptyModalContainer}>
          <>
            <Image source={emptyResult} style={currentStyle.emptyImageModal} />
            <Text style={currentStyle.withoutResultsText}>Sin resultados</Text>
            <Text style={currentStyle.tryAgainText}>
              {t('add_car:model_car_modal:try_search')}
            </Text>
          </>
        </View>
      }
      renderItem={({item}) => (
        <TouchableOpacity
          style={currentStyle.itemModalContainer}
          key={item.objectID}
          activeOpacity={0.6}
          onPress={() =>
            props.onPress({
              brandID: item.brandID,
              brandName: item.brandName,
              modelName: item.modelName,
              objectID: item.objectID,
              availableYears: item.availableYears,
            })
          }>
          <Text style={currentStyle.modelCarItem}>
            {`${item.brandName} ${item.modelName}`}
          </Text>
          <IconRightArrow color="#000" size={0} />
        </TouchableOpacity>
      )}
    />
  );
}

function SearchBox(props) {
  const {query, refine} = useSearchBox();
  const currentStyle = style();
  const [inputValue, setInputValue] = useState(query);
  const inputRef = useRef(null);

  useEffect(() => {
    const loadingTimeout = setTimeout(() => {
      props.handleInput(inputValue);
      refine(inputValue);
    }, 500);

    return () => {
      if (loadingTimeout) {
        clearTimeout(loadingTimeout);
      }
    };
  }, [inputValue]);

  function setQuery(newQuery: string) {
    setInputValue(newQuery);
    // props.handleInput(newQuery);
    // refine(newQuery);
  }

  // Track when the InstantSearch query changes to synchronize it with
  // the React state.
  // We bypass the state update if the input is focused to avoid concurrent
  // updates when typing.
  // if (query !== inputValue && !inputRef.current?.isFocused()) {
  //   setInputValue(query);
  // }

  return (
    <View style={[currentStyle.headerModalContainer]}>
      <Input
        rightIcon={
          <View>
            <IconSearch />
          </View>
        }
        refs={inputRef}
        title={'Busca tu vehículo'}
        value={inputValue}
        onChangeText={setQuery}
        placeholder={'Buscar'}
        clearButtonMode="while-editing"
        autoCapitalize="none"
        autoCorrect={false}
        spellCheck={false}
      />
    </View>
  );
}

export default SearchVehicleModal;

In iOS everything works, the problem is in android

@SalahAdDin
Copy link

It is happening to us using typesense:0.24 docker container.

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

3 participants