React Native ref.injectJavascript в WebView всегда не определен

#javascript #reactjs #react-native

#javascript #reactjs ( реакция ) #реагировать-родной #reactjs #react-native

Вопрос:

У меня есть простой функциональный компонент с WebView внутри TabNavigator, в который я хотел бы ввести некоторый javascript, когда вкладка сфокусирована следующим образом:

 import React, {useRef, useEffect} from 'react';
import {WebView} from 'react-native-webview';

export default (props) => {

  const webViewRef = useRef();

  React.useEffect(() => {
    const unsubscribe = props.navigation.addListener('focus', () => {
      webViewRef.current.injectJavascript('console.log("Hello World")');
    });
    return unsubscribe;
  }, []);

  return (
    <WebView ref={webViewRef} />
  );
}
  

По какой-то причине webViewRef всегда не определено в слушателе.

Если я сделаю что-то вроде <WebView ref={(r) => console.log(r)} /> , я получу что-то вроде следующего:

скриншот

Редактировать:

Простая настройка предоставленного примера работает, поэтому, я полагаю, мне придется выяснить, что происходит в моем коде:

 import React, { useRef } from 'react'
import { View } from 'react-native'
import { WebView } from 'react-native-webview'

export default () => {

  const webViewRef = useRef(null);

  const run = `
    document.body.style.backgroundColor = 'blue';
    true;
  `

  setTimeout(() => {
    webViewRef.current.injectJavaScript(run)
  }, 3000)

  return (
    <View style={{ flex: 1 }}>
      <WebView
        ref={webViewRef}
        source={{
          uri:
            'https://github.com/react-native-community/react-native-webview',
        }}
      />
    </View>
  )
}
  

РЕДАКТИРОВАТЬ 2: Корректировка простого примера и попытка использовать ссылку внутри прослушивателя не работает:

 import React, { useRef } from 'react'
import { View } from 'react-native'
import { WebView } from 'react-native-webview'

export default (props) => {

  const webViewRef = useRef(null);



  const run = `
    document.body.style.backgroundColor = 'blue';
    true;
  `
  const handleLoadEnd = () => {
    props.navigation.addListener('focus', () => {
      webViewRef.current.injectJavascript(run)
    })
  }

  return (
    <View style={{ flex: 1 }}>
      <WebView
        ref={webViewRef}
        source={{
          uri:
            'https://github.com/react-native-community/react-native-webview',
        }}
        onLoadEnd={handleLoadEnd}
      />
    </View>
  )
}
  

Правка 3: useFocusEffect также имеет ту же проблему:

   useFocusEffect(
    React.useCallback(() => {
      webViewRef.current.injectJavascript('alert("HI")')
    }, [props.navigation])
  )
  

Источники:

Комментарии:

1. Не могли бы вы проверить, что вы можете получить доступ webViewRef.current из addListener?

2. Это всегда кажется неопределенным, это так сбивает с толку.

3. Можете ли вы протестировать свой код с помощью setTimeout с задержкой 3000-5000 мс? Если ссылка все еще не определена, значит, что-то не так. А также вы можете создать эффект использования внутри массива, который вы передаете ref. Если он установлен, он будет вызван автоматически

4. В том, как это работает со слушателем, определенно есть что-то странное — поскольку я могу использовать ссылку, если она вызывается непосредственно внутри useEffect . В прослушивателе, даже с таймаутом, это не работает.

Ответ №1:

О боже, это действительно еще один из тех эпических дней, когда волосы тянутся:

   webViewRef.injectJavascript < BAD
  webViewRef.injectJavaScript < GOOD
  

Кто-нибудь, пожалуйста, верните последние 4 часа моей жизни

Комментарии:

1. спасибо вам за это, эта заглавная буква S в JavaScript действительно непослушна.

2. Забавно, что сегодня у меня была одна из этих ужасных ситуаций с библиотекой, в которой нужной мне опции lazyLoad не было lazyload

3. большое спасибо, чувак! Я буквально потратил часы, пытаясь решить эту проблему!

Ответ №2:

Ссылка будет установлена, если onLoadEnd событие сработало. Итак, вы должны настроить свой код следующим образом:

 export default (props) => {

  const webViewRef = useRef();

  const handleLoadEnd = () => {
    props.navigation.addListener('focus', () => {
      webViewRef.current.injectJavascript('console.log("Hello World")');
    });
  }

  return (
    <WebView ref={webViewRef} onLoadEnd={handleLoadEnd}/>
  );
}
  

У меня есть рабочий пример. Смотрите здесь https://github.com/Tracer1337/MRGVP/blob/master/vertretungsplan/components/PaginatedWebview/PaginatedWebview.js

Комментарии:

1. Спасибо, это имеет смысл, и я добавил слушателя в onLoadEnd , но у меня все еще та же проблема, webViewRef не определена:(

2. Так что, к сожалению, это не работает, и я думаю, что это можно сузить до слушателя, пожалуйста, смотрите пример в Edit 2 моем посте