الفرق بين المراجعتين لصفحة: «ReactNative/network»

من موسوعة حسوب
لا ملخص تعديل
طلا ملخص تعديل
 
(3 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:التعامل مع الشبكات في React Native}}</noinclude>
<noinclude>{{DISPLAYTITLE:الاتصال بالشبكة في React Native}}</noinclude>
==التشبيك (Networking)==
تحتاج العديد من تطبيقات الجوال إلى تحميل الموارد من عنوان URL بعيد، فقد ترغب بإرسال طلب POST إلى واجهة REST برمجيّة، أو قد تحتاج ببساطة إلى جلب محتوًى ثابت من خادم آخر.
تحتاج العديد من تطبيقات الجوال إلى تحميل الموارد من عنوان URL بعيد. قد ترغب بإرسال طلب POST إلى واجهة REST برمجيّة، أو قد تحتاج ببساطة إلى جلب محتوًى ثابت من خادم آخر.


==استعمال أداة Fetch==
==استخدام Fetch==
يوفر React Native [https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API واجهة Fetch] البرمجية للتعامل مع الشبكات. ستكون أداة Fetch مألوفة بالنسبة لك إن استخدمت XMLHttpRequest أو واجهات التشبيك البرمجية الأخرى سابقًا. يمكنك الرجوع إلى [https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch دليل MDN حول كيفيّة استخدام Fetch] للحصول على معلومات إضافية.
يوفر React Native [https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API واجهة Fetch] البرمجية للاتصال بالشبكة. ستكون الواجهة Fetch مألوفة بالنسبة لك إن استخدمت <code>XMLHttpRequest</code> أو واجهات التشبيك البرمجية الأخرى سابقًا. يمكنك الرجوع إلى مقال [https://academy.hsoub.com/programming/javascript/%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-fetch-%D9%81%D9%8A-javascript-r739/ حول كيفيّة استخدام Fetch] في أكاديمية حسوب للحصول على معلومات إضافية.


===إرسال الطلبات===
===إنشاء الطلبات===
لجلب محتوًى من عنوان URL مُعيّن، مرِّره للدالة ‎<code>fetch()</code>‎ ببساطة كما يلي:
لجلب محتوًى من عنوان URL مُعيّن، مرِّره للدالة ‎<code>fetch()</code>‎ ببساطة كما يلي:


سطر 12: سطر 11:
fetch('https://mywebsite.com/mydata.json');
fetch('https://mywebsite.com/mydata.json');
</syntaxhighlight>
</syntaxhighlight>
تقبل الدالة ‎<code>fetch()</code>‎ كذلك معاملًا ثانيًّا اختياريًّا يسمح لك بتخصيص طلب HTTP الذي تُريد إرساله. قد ترغب في تحديد ترويسات (headers) إضافية أو تقديم طلب POST عوضًا عن طلب GET:
تقبل الدالة ‎<code>fetch()</code>‎ كذلك معاملًا ثانيًّا اختياريًّا يسمح لك بتخصيص طلب HTTP الذي تُريد إرساله، قد ترغب في تحديد ترويسات (headers) إضافية أو تقديم طلب POST عوضًا عن طلب GET:
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
fetch('https://mywebsite.com/endpoint/', {
fetch('https://mywebsite.com/endpoint/', {
سطر 18: سطر 17:
   headers: {
   headers: {
     Accept: 'application/json',
     Accept: 'application/json',
     'Content-Type': 'application/json',
     'Content-Type': 'application/json'
   },
   },
   body: JSON.stringify({
   body: JSON.stringify({
     firstParam: 'yourValue',
     firstParam: 'yourValue',
     secondParam: 'yourOtherValue',
     secondParam: 'yourOtherValue'
   }),
   })
});
});
</syntaxhighlight>
</syntaxhighlight>
ألقِ نظرة على [https://developer.mozilla.org/en-US/docs/Web/API/Request توثيق Fetch Request] لقائمة كاملة بالخاصيات الممكنة.
ألقِ نظرة على [https://developer.mozilla.org/en-US/docs/Web/API/Request توثيق Fetch Request] لقائمة كاملة بالخاصيات الممكنة.


===التعامل مع الرد===
===التعامل مع الاستجابة===
توضح الأمثلة أعلاه كيفيّة إرسال الطلبات، لكنّك ستحتاج إلى التّعامل مع الرّد في كثير من الحالات.
توضح الأمثلة أعلاه كيفيّة إرسال الطلبات، لكنّك ستحتاج إلى التّعامل مع الرّد في كثير من الحالات.


التشبيك عملية غير متزامنة (asynchronous) بطبيعتها. تعيد توابع Fetch [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise وعدًا (Promise)] يسهّل كتابة شيفرة برمجية تعمل بطريقة غير متزامنة:
التشبيك عملية غير متزامنة (asynchronous) بطبيعتها. تعيد توابع Fetch [[JavaScript/Promise/Using promises|وعدًا (Promise)]] يسهّل كتابة شيفرة برمجية تعمل بطريقة غير متزامنة:
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
function getMoviesFromApiAsync() {
const getMoviesFromApi = () => {
   return fetch('https://facebook.github.io/react-native/movies.json')
   return fetch('https://reactnative.dev/movies.json')
     .then((response) => response.json())
     .then((response) => response.json())
     .then((responseJson) => {
     .then((json) => {
       return responseJson.movies;
       return json.movies;
     })
     })
     .catch((error) => {
     .catch((error) => {
       console.error(error);
       console.error(error);
     });
     });
}
};
</syntaxhighlight>
</syntaxhighlight>
يمكنك أيضًا استخدام صيغة ‎<code>[[JavaScript/async function|async]]</code>‎‎‎/[[JavaScript/await|<code>await</code>‎]] المقترحة في نسخة ES2017 من لغة JavaScript في تطبيقات React Native:
يمكنك أيضًا استخدام صيغة ‎<code>[[JavaScript/async function|async]]</code>‎‎‎/[[JavaScript/await|<code>await</code>‎]] في تطبيقات React Native:
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
async function getMoviesFromApi() {
const getMoviesFromApiAsync = async () => {
   try {
   try {
     let response = await fetch(
     let response = await fetch(
       'https://facebook.github.io/react-native/movies.json',
       'https://reactnative.dev/movies.json'
     );
     );
     let responseJson = await response.json();
     let json = await response.json();
     return responseJson.movies;
     return json.movies;
   } catch (error) {
   } catch (error) {
     console.error(error);
     console.error(error);
   }
   }
}
};
</syntaxhighlight>
</syntaxhighlight>
'''ملاحظة:''' لا تنسَ إمساك (catch) أي أخطاء قد ترميها ‎<code>fetch</code>‎، وإلا ستمرّ بصمت وسيصعب حلّ المشاكل التي قد تنشأ جرّاء ذلك.
'''ملاحظة:''' لا تنسَ إمساك (catch) أي أخطاء قد ترميها ‎<code>fetch</code>‎، وإلا سترمى هذه الأخطاء بصمتٍ.
 
* [https://snack.expo.dev/@hsoubwiki/fetch-example-function-component مثال لمكوّن الدالة (Function Component)]:
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
import React from 'react';
import React, { useEffect, useState } from 'react';
import { FlatList, ActivityIndicator, Text, View } from 'react-native';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';
 
export default App = () => {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);
 
  useEffect(() => {
    fetch('https://reactnative.dev/movies.json')
      .then((response) => response.json())
      .then((json) => setData(json.movies))
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  }, []);
 
  return (
    <View style={{ flex: 1, padding: 24 }}>
      {isLoading ? <ActivityIndicator/> : (
        <FlatList
          data={data}
          keyExtractor={({ id }, index) => id}
          renderItem={({ item }) => (
            <Text>{item.title}, {item.releaseYear}</Text>
          )}
        />
      )}
    </View>
  );
};
</syntaxhighlight>


export default class FetchExample extends React.Component {
* [https://snack.expo.dev/@hsoubwiki/fetch-example-class-component مثال لمكوّن الصنف (Class Component)]:
<syntaxhighlight lang="javascript">
import React, { Component } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';


   constructor(props){
export default class App extends Component {
   constructor(props) {
     super(props);
     super(props);
     this.state ={ isLoading: true}
 
     this.state = {
      data: [],
      isLoading: true
    };
   }
   }


   componentDidMount(){
   componentDidMount() {
     return fetch('https://facebook.github.io/react-native/movies.json')
     fetch('https://reactnative.dev/movies.json')
       .then((response) => response.json())
       .then((response) => response.json())
       .then((responseJson) => {
       .then((json) => {
 
         this.setState({ data: json.movies });
         this.setState({
          isLoading: false,
          dataSource: responseJson.movies,
        }, function(){
 
        });
 
       })
       })
       .catch((error) =>{
       .catch((error) => console.error(error))
         console.error(error);
      .finally(() => {
         this.setState({ isLoading: false });
       });
       });
   }
   }
</syntaxhighlight>'''ملاحظة:''' تمنع منصّة iOS افتراضيًّا أي طلبٍ غير مشفّر باستخدام SSL. إن احتجت إلى جلب بيانات من عنوان URL غير مُشفّر (الذي يبدأ بالمقطع ‎<code>http</code>‎ عوضًا عن ‎<code>https</code>‎) ، فستحتاج أولا إلى إضافة [[ReactNative/integration with existing apps|استثناء App Transport Security]] . إذا كنت تعرف مسبقًا النطاقات التي ستحتاج إلى الوصول إليها، فمن الأفضل إضافة استثناءات لهذه النطاقات فقط؛ إذا لم تكن النطاقات معروفة حتى وقت تشغيل التطبيق فيمكنك [[ReactNative/integration with existing apps|تعطيل ATS بالكامل]]. ومع ذلك لاحظ أنه اعتبارًا من يناير 2017 تتطلب [https://forums.developer.apple.com/thread/48979 مراجعة سوق Apple للتطبيقات] تبريرات معقولة لتعطيل ATS. راجع [https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33 توثيق Apple] لمزيد من المعلومات.


 
أما على منصة Android  فتمنع حركة مرور النص غير المشفر بشكلٍ افتراضيًّ اعتبارًا من الواجهات البرمجية من المستوى 28، يمكن تغيير هذا السلوك بضبط <code>android:usesCleartextTraffic</code> في ملف بيان (manifest file) التطبيق.
 
  render(){
 
    if(this.state.isLoading){
      return(
        <View style={{flex: 1, padding: 20}}>
          <ActivityIndicator/>
        </View>
      )
    }
 
    return(
      <View style={{flex: 1, paddingTop:20}}>
        <FlatList
          data={this.state.dataSource}
          renderItem={({item}) => <Text>{item.title}, {item.releaseYear}</Text>}
          keyExtractor={({id}, index) => id}
        />
      </View>
    );
  }
}
</syntaxhighlight>
'''ملاحظة:''' تمنع منصّة iOS افتراضيًّا أي طلبٍ غير مشفّر باستخدام SSL. إن احتجت إلى جلب بيانات من عنوان URL غير مُشفّر (الذي يبدأ بالمقطع ‎<code>http</code>‎ عوضًا عن ‎<code>https</code>‎) ، فستحتاج أولا إلى إضافة [[ReactNative/integration with existing apps|استثناء App Transport Security]] . إذا كنت تعرف مسبقًا النطاقات التي ستحتاج إلى الوصول إليها، فمن الأفضل إضافة استثناءات لهذه النطاقات فقط؛ إذا لم تكن النطاقات معروفة حتى وقت تشغيل التطبيق، فيمكنك [[ReactNative/integration with existing apps|تعطيل ATS بالكامل]]. ومع ذلك لاحظ أنه اعتبارًا من يناير 2017، تتطلب [https://forums.developer.apple.com/thread/48979 مراجعة سوق Apple للتطبيقات] تبريرات معقولة لتعطيل ATS. راجع [https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33 توثيق Apple] لمزيد من المعلومات.


==استعمال مكتبات تشبيك أخرى==
==استعمال مكتبات تشبيك أخرى==
واجهةُ [https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest XMLHttpRequest]  مضمَّنة مسبقًا في React Native. ما يعني أنّك تستطيع استخدام مكتباتِ طرفٍ ثالث (third party libraries) مثل ‎[https://github.com/niftylettuce/frisbee frisbee]‎ أو ‎‎[https://github.com/mzabriskie/axios axios] التي تعتمد عليها، أو يمكنك استخدام <code>XMLHttpRequest</code> مباشرة إذا كنت تفضل ذلك.
ضُمّنت واجهةُ [https://academy.hsoub.com/questions/13084-javascript-%D8%B7%D8%B1%D9%8A%D9%82%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-fetch-%D9%88-xmlhttprequest/ XMLHttpRequest]  مسبقًا في React Native، ما يعني أنّك تستطيع استخدام مكتباتِ خارجية (third party libraries) مثل ‎[https://github.com/niftylettuce/frisbee frisbee]‎ أو ‎‎[https://github.com/mzabriskie/axios axios]التي تعتمد عليها، أو يمكنك استخدام <code>XMLHttpRequest</code> مباشرة إذا كنت تفضل ذلك.
<syntaxhighlight lang="javascript">
<syntaxhighlight lang="javascript">
var request = new XMLHttpRequest();
var request = new XMLHttpRequest();
سطر 133: سطر 141:
request.send();
request.send();
</syntaxhighlight>
</syntaxhighlight>
'''ملاحظة:''' يختلف نموذج الأمان الخاص بواجهة <code>XMLHttpRequest</code> عن ذلك الموجود على الويب، إذ لا يوجد مفهوم [http://en.wikipedia.org/wiki/Cross-origin_resource_sharing CORS] في التطبيقات الأصيلة.
'''ملاحظة:''' يختلف نموذج الأمان الخاص بواجهة <code>XMLHttpRequest</code> عن ذلك الموجود على الويب، إذ لا يوجد مفهوم [https://academy.hsoub.com/programming/javascript/%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-fetch-%D9%85%D8%B9-%D8%A7%D9%84%D8%B7%D9%84%D8%A8%D8%A7%D8%AA-%D8%B0%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B5%D9%84-%D8%A7%D9%84%D9%85%D8%AE%D8%AA%D9%84%D8%B7-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r1296/ CORS] في التطبيقات الأصيلة.


==دعم WebSocket==
==دعم WebSocket==
سطر 142: سطر 150:


ws.onopen = () => {
ws.onopen = () => {
   // فُتِح الاتّصال
   // فتح الاتصال
   ws.send('something'); // send a message
   ws.send('something'); // send a message
};
};


ws.onmessage = (e) => {
ws.onmessage = (e) => {
   // استُقبِلَت رسالة
   // استقبلت رسالة
   console.log(e.data);
   console.log(e.data);
};
};
سطر 157: سطر 165:


ws.onclose = (e) => {
ws.onclose = (e) => {
   // أغلِق الاتصال
   // أغلق الاتصال
   console.log(e.code, e.reason);
   console.log(e.code, e.reason);
};
};
</syntaxhighlight>
</syntaxhighlight>
==تهانينا!==
مبارك وصولك إلى هذه المرحلة من سلسلة الدروس هذه، يُمكنك الآن بناء تطبيقات جوال أصيلة بالمعرفة التي حصلت عليها! انظر [[ReactNative/more resources|هذه الصفحة]] للمزيد من الموارد وما يوفّره مجتمع React Native من أدوات وأمثلة وغير ذلك.


للمزيد من المعلومات حول  React Native، انظر [[ReactNative|صفحة التوثيق الرئيسيّة]].
== المشكلات المعروفة في fetch والمصادقة المعتمدة على ملفات تعريف الارتباط (cookies) ==
لا تعمل الخيارات التالية في fetch:
 
* <code>redirect:manual</code>
* <code>credentials:omit</code>
* عند وجود ترويسات لها الاسم نفسه في Android  تؤخذ الأخيرة فقط، يمكن إيجاد حل مؤقت في  https://github.com/facebook/react-native/issues/18837#issuecomment-398779994.
* المصادقة المعتمدة على ملفات تعريف الارتباط (cookies) غير مستقرة حاليًا، يمكنك مشاهدة أهم المشكلات في https://github.com/facebook/react-native/issues/23185,
* عند إعادة التوجيه في iOS باستخدام <code>302</code> -كحدٍّ أدنى- وإذا كانت الترويسة <code>Set-Cookie</code> موجودة فلن يعيَّن ملف تعريف الارتباط بشكلٍ صحيح، وبما أن إعادة التوجيه لا تعالج بشكلً يدويٍَ  فيمكن أن ينتج سيناريو حدوث طلبات لا نهائية إذا كانت إعادة التوجيه نتيجة جلسة منتهية الصلاحية.
 
== ضبط NSURLSession في iOS ==
قد تتطلب بعض التطبيقات توفير ضبط <code>NSURLSessionConfiguration</code> خاص من أجل <code>NSURLSession</code> المستخدم في إجراء إرسال طلبيات عبر الشبكة في تطبيقات React Native على نظام iOS. مثلًا، قد تحتاج إلى ضبط عميل مستخدم user agent خاص لجميع طلبيات الشبكة القادمة من تطبيق أو مزود <code>NSURLSession</code> مع ضبط <code>NSURLSessionConfiguration</code> مؤقت، وهنا تسمح الدالة <code>RCTSetCustomNSURLSessionConfigurationProvider</code> بإجراء مثل هذا الضبط المخصص. تذكر بإضافة الاستيراد التالي إلى الملف الذي ستستدعي فيه الدالة <code>RCTSetCustomNSURLSessionConfigurationProvider</code>:<syntaxhighlight lang="js">
#import <React/RCTHTTPRequestHandler.h>
</syntaxhighlight>يجب أن تُستدعى الدالة <code>RCTSetCustomNSURLSessionConfigurationProvider</code> في أول دورة حياة التطبيق وبذلك تكون متاحة دومًا متى ما دعت الحالة لاستعمالها من طرف [[React]]. انظر الشيفرة التالية مثلًا:<syntaxhighlight lang="js">
-(void)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 
  // set RCTSetCustomNSURLSessionConfigurationProvider
  RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    // configure the session
    return configuration;
  });
 
  // set up React
  _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
}
</syntaxhighlight>
 
== مصادر ==
== مصادر ==
* [https://facebook.github.io/react-native/docs/network صفحة Networking في توثيق React Native الرسمي.]
* [https://facebook.github.io/react-native/docs/network صفحة Networking في توثيق React Native الرسمي.]
[[تصنيف:ReactNative]]
[[تصنيف:ReactNative]]
[[تصنيف:React Native Docs]]

المراجعة الحالية بتاريخ 13:44، 9 أكتوبر 2021

تحتاج العديد من تطبيقات الجوال إلى تحميل الموارد من عنوان URL بعيد، فقد ترغب بإرسال طلب POST إلى واجهة REST برمجيّة، أو قد تحتاج ببساطة إلى جلب محتوًى ثابت من خادم آخر.

استخدام Fetch

يوفر React Native واجهة Fetch البرمجية للاتصال بالشبكة. ستكون الواجهة Fetch مألوفة بالنسبة لك إن استخدمت XMLHttpRequest أو واجهات التشبيك البرمجية الأخرى سابقًا. يمكنك الرجوع إلى مقال حول كيفيّة استخدام Fetch في أكاديمية حسوب للحصول على معلومات إضافية.

إنشاء الطلبات

لجلب محتوًى من عنوان URL مُعيّن، مرِّره للدالة ‎fetch()‎ ببساطة كما يلي:

fetch('https://mywebsite.com/mydata.json');

تقبل الدالة ‎fetch()‎ كذلك معاملًا ثانيًّا اختياريًّا يسمح لك بتخصيص طلب HTTP الذي تُريد إرساله، قد ترغب في تحديد ترويسات (headers) إضافية أو تقديم طلب POST عوضًا عن طلب GET:

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue'
  })
});

ألقِ نظرة على توثيق Fetch Request لقائمة كاملة بالخاصيات الممكنة.

التعامل مع الاستجابة

توضح الأمثلة أعلاه كيفيّة إرسال الطلبات، لكنّك ستحتاج إلى التّعامل مع الرّد في كثير من الحالات.

التشبيك عملية غير متزامنة (asynchronous) بطبيعتها. تعيد توابع Fetch وعدًا (Promise) يسهّل كتابة شيفرة برمجية تعمل بطريقة غير متزامنة:

const getMoviesFromApi = () => {
  return fetch('https://reactnative.dev/movies.json')
    .then((response) => response.json())
    .then((json) => {
      return json.movies;
    })
    .catch((error) => {
      console.error(error);
    });
};

يمكنك أيضًا استخدام صيغة ‎async‎‎‎/await في تطبيقات React Native:

const getMoviesFromApiAsync = async () => {
  try {
    let response = await fetch(
      'https://reactnative.dev/movies.json'
    );
    let json = await response.json();
    return json.movies;
  } catch (error) {
    console.error(error);
  }
};

ملاحظة: لا تنسَ إمساك (catch) أي أخطاء قد ترميها ‎fetch‎، وإلا سترمى هذه الأخطاء بصمتٍ.

import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';

export default App = () => {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://reactnative.dev/movies.json')
      .then((response) => response.json())
      .then((json) => setData(json.movies))
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  }, []);

  return (
    <View style={{ flex: 1, padding: 24 }}>
      {isLoading ? <ActivityIndicator/> : (
        <FlatList
          data={data}
          keyExtractor={({ id }, index) => id}
          renderItem={({ item }) => (
            <Text>{item.title}, {item.releaseYear}</Text>
          )}
        />
      )}
    </View>
  );
};
import React, { Component } from 'react';
import { ActivityIndicator, FlatList, Text, View } from 'react-native';

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      data: [],
      isLoading: true
    };
  }

  componentDidMount() {
    fetch('https://reactnative.dev/movies.json')
      .then((response) => response.json())
      .then((json) => {
        this.setState({ data: json.movies });
      })
      .catch((error) => console.error(error))
      .finally(() => {
        this.setState({ isLoading: false });
      });
  }

ملاحظة: تمنع منصّة iOS افتراضيًّا أي طلبٍ غير مشفّر باستخدام SSL. إن احتجت إلى جلب بيانات من عنوان URL غير مُشفّر (الذي يبدأ بالمقطع ‎http‎ عوضًا عن ‎https‎) ، فستحتاج أولا إلى إضافة استثناء App Transport Security . إذا كنت تعرف مسبقًا النطاقات التي ستحتاج إلى الوصول إليها، فمن الأفضل إضافة استثناءات لهذه النطاقات فقط؛ إذا لم تكن النطاقات معروفة حتى وقت تشغيل التطبيق فيمكنك تعطيل ATS بالكامل. ومع ذلك لاحظ أنه اعتبارًا من يناير 2017 تتطلب مراجعة سوق Apple للتطبيقات تبريرات معقولة لتعطيل ATS. راجع توثيق Apple لمزيد من المعلومات.

أما على منصة Android فتمنع حركة مرور النص غير المشفر بشكلٍ افتراضيًّ اعتبارًا من الواجهات البرمجية من المستوى 28، يمكن تغيير هذا السلوك بضبط android:usesCleartextTraffic في ملف بيان (manifest file) التطبيق.

استعمال مكتبات تشبيك أخرى

ضُمّنت واجهةُ XMLHttpRequest مسبقًا في React Native، ما يعني أنّك تستطيع استخدام مكتباتِ خارجية (third party libraries) مثل ‎frisbee‎ أو ‎‎axiosالتي تعتمد عليها، أو يمكنك استخدام XMLHttpRequest مباشرة إذا كنت تفضل ذلك.

var request = new XMLHttpRequest();
request.onreadystatechange = (e) => {
  if (request.readyState !== 4) {
    return;
  }

  if (request.status === 200) {
    console.log('success', request.responseText);
  } else {
    console.warn('error');
  }
};

request.open('GET', 'https://mywebsite.com/endpoint/');
request.send();

ملاحظة: يختلف نموذج الأمان الخاص بواجهة XMLHttpRequest عن ذلك الموجود على الويب، إذ لا يوجد مفهوم CORS في التطبيقات الأصيلة.

دعم WebSocket

يدعم React Native بروتوكول WebSockets كذلك، والذي يوفر قنوات اتصال ثنائية الاتجاه (full-duplex communication) عبر اتصال TCP واحد.

var ws = new WebSocket('ws://host.com/path');

ws.onopen = () => {
  // فتح الاتصال
  ws.send('something'); // send a message
};

ws.onmessage = (e) => {
  // استقبلت رسالة
  console.log(e.data);
};

ws.onerror = (e) => {
  // حدث خطأ
  console.log(e.message);
};

ws.onclose = (e) => {
  // أغلق الاتصال
  console.log(e.code, e.reason);
};

المشكلات المعروفة في fetch والمصادقة المعتمدة على ملفات تعريف الارتباط (cookies)

لا تعمل الخيارات التالية في fetch:

  • redirect:manual
  • credentials:omit
  • عند وجود ترويسات لها الاسم نفسه في Android تؤخذ الأخيرة فقط، يمكن إيجاد حل مؤقت في https://github.com/facebook/react-native/issues/18837#issuecomment-398779994.
  • المصادقة المعتمدة على ملفات تعريف الارتباط (cookies) غير مستقرة حاليًا، يمكنك مشاهدة أهم المشكلات في https://github.com/facebook/react-native/issues/23185,
  • عند إعادة التوجيه في iOS باستخدام 302 -كحدٍّ أدنى- وإذا كانت الترويسة Set-Cookie موجودة فلن يعيَّن ملف تعريف الارتباط بشكلٍ صحيح، وبما أن إعادة التوجيه لا تعالج بشكلً يدويٍَ فيمكن أن ينتج سيناريو حدوث طلبات لا نهائية إذا كانت إعادة التوجيه نتيجة جلسة منتهية الصلاحية.

ضبط NSURLSession في iOS

قد تتطلب بعض التطبيقات توفير ضبط NSURLSessionConfiguration خاص من أجل NSURLSession المستخدم في إجراء إرسال طلبيات عبر الشبكة في تطبيقات React Native على نظام iOS. مثلًا، قد تحتاج إلى ضبط عميل مستخدم user agent خاص لجميع طلبيات الشبكة القادمة من تطبيق أو مزود NSURLSession مع ضبط NSURLSessionConfiguration مؤقت، وهنا تسمح الدالة RCTSetCustomNSURLSessionConfigurationProvider بإجراء مثل هذا الضبط المخصص. تذكر بإضافة الاستيراد التالي إلى الملف الذي ستستدعي فيه الدالة RCTSetCustomNSURLSessionConfigurationProvider:

#import <React/RCTHTTPRequestHandler.h>

يجب أن تُستدعى الدالة RCTSetCustomNSURLSessionConfigurationProvider في أول دورة حياة التطبيق وبذلك تكون متاحة دومًا متى ما دعت الحالة لاستعمالها من طرف React. انظر الشيفرة التالية مثلًا:

-(void)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  // set RCTSetCustomNSURLSessionConfigurationProvider
  RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
     NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
     // configure the session
     return configuration;
  });

  // set up React
  _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
}

مصادر