В этом посте мы поговорим о новой функции, доступной в React 16.8.0, Hooks — новом способе управления состоянием вашего приложения. С помощью этой новой функции можно создавать компоненты чище, проще и с помощью функциональных компонентов, да, вы правильно поняли, больше не нужно использовать классы, и вы также может обрабатывать методы жизненного цикла.

Цель этого поста — узнать, как использовать Hooks в приложениях React Native. Сначала я покажу вам базовый пример в очень распространенном случае использования, таком как форма. Кроме того, я объясню, как вы можете создавать свои собственные хуки и как справляться с их побочными эффектами.

Если вам нужна дополнительная информация о хуках, вы можете посмотреть здесь. Также стоит посмотреть это видео Софи Алперт и Дэна Абрамова, где они более подробно и с большим контекстом объясняют React Hooks.

Предпосылки

Чтобы запустить примеры кода из этого поста, вам необходимо установить react-native 0.59 или более раннюю версию, потому что именно она представляет хуки в React. RN 0.59 все еще является RC-версией, поэтому, чтобы протестировать ее, вы можете сделать это следующим образом:

react-native init ReactNativeHooks –version react-native@next

Если вы хотите проверить сдачу в RN 0.59, это ваше место.

Первый компонент

Я думаю, что лучший способ объяснить крючки — это показать пример того, как они используются в простом случае использования, таком как форма, где вам нужно заполнить адрес электронной почты, имя, а затем отправить это (очень распространенный вариант использования, очевидно, что отправка не будет реальной)

const FormHook = () => {
  const [formState, setForm] = useState({ email: "", name: "" });
return (
    <View style={styles.container}>
      <Text style={styles.count}>Name</Text>
      <TextInput
        style={{
          height: 40,
          borderColor: "gray",
          borderWidth: 1,
          width: 200,
          padding: 7
        }}
        onChangeText={name => setForm({ ...formState, name })}
        value={formState.name}
      />
      <Text style={styles.count}>Email</Text>
      <TextInput
        style={{
          height: 40,
          borderColor: "gray",
          borderWidth: 1,
          width: 200,
          padding: 7
        }}
        onChangeText={email => setForm({ ...formState, email })}
        value={formState.email}
      />
      <Button onPress={() => setForm({ email: "", name: "" })} title="Send" />
    </View>
  );
};
export default FormHook;

В приведенном выше примере мы можем видеть простоту хуков, я создал форму в функциональном компоненте (больше никаких классов, ага!!!!) и добавил крючок вверху, один из первое правило хуков заключается в том, что вам нужно объявить их в верхней части ваших функций:

const [formState, setForm] = useState({email: ‘’, name: ‘’})

Когда вы вызываете useState, сначала вам нужно передать начальное состояние, а затем, благодаря деконструкции массива, вы получите:

  • первый параметр: текущее состояние формы.
  • второй: это функция для изменения вашего текущего состояния.

Как видно из примера, вам не нужно привязывать функцию setForm к этому или чему-то подобному, потому что он уже находится в той же области видимости.

Побочные эффекты

В React 16.8 также представлен хук под названием useEffect, созданный для обработки побочных эффектов в функциональных компонентах, он похож на componentDidMount или componentDidUpdate для классов.

Что такое побочные эффекты? Побочные эффекты — это все операции, выполняемые за пределами локальной среды, в которой они выполняются, например, сетевой запрос, доступ к базам данных и так далее.

Вот пример предыдущего фрагмента с useEffect:

import React, {useState, useEffect} from 'react'
import {
  Platform,
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  TextInput,
  Button,
  NetInfo,
} from 'react-native'
type Props = {}
const FormHook = () => {
  const [formState, setForm] = useState({email: '', name: '', isOnline: true})
const handleFirstConnectivityChange = connectionInfo => {
    setForm({…formState, isOnline: connectionInfo.type !== 'none'})
  }
useEffect(() => {
    NetInfo.addEventListener('connectionChange', handleFirstConnectivityChange)
return () => {
      NetInfo.removeEventListener(
        'connectionChange',
        handleFirstConnectivityChange
      )
    }
  })
return (
    <View style={styles.container}>
      <Text style={styles.count}>Name</Text>
      <TextInput
        style={{
          height: 40,
          borderColor: 'gray',
          borderWidth: 1,
          width: 200,
          padding: 7,
        }}
        onChangeText={name => setForm({…formState, name})}
        value={formState.name}
      />
      <Text style={styles.count}>Email</Text>
      <TextInput
        style={{
          height: 40,
          borderColor: 'gray',
          borderWidth: 1,
          width: 200,
          padding: 7,
        }}
        onChangeText={email => setForm({…formState, email})}
        value={formState.email}
      />
      <Button
        disabled={!formState.isOnline}
        onPress={() => setForm({…formState, email: '', name: ''})}
        title="Send"
      />
    </View>
  )
}
export default FormHook

В приведенном выше примере мы используем хук useEffect для подписки на изменения сетевой информации с помощью NetInfo, также, как вы можете видеть, он обрабатывается, когда этот компонент размонтирован и нам нужно почистить слушателя, все это делается здесь:

useEffect(() => {
  NetInfo.addEventListener("connectionChange", handleFirstConnectivityChange);
return () => {
    NetInfo.removeEventListener(
      "connectionChange",
      handleFirstConnectivityChange
    );
  };
});

Разве это не намного чище? вы можете обрабатывать побочные эффекты внутри вашего функционального компонента без необходимости связывать функции с классами.

Пользовательские крючки

Что, если то, что мы действительно хотим, это повторное использование хуков, которые мы ранее создали, чтобы мы не повторяли наш код в каждом компоненте, да, это возможно, в следующем примере вы увидите, как я создал хук в React Native для иметь возможность проверить, находится ли ваше устройство в сети или нет:

import React, { useState, useEffect } from "react";
import { NetInfo } from "react-native";
export default () => {
  const [isOnline, setIsOnline] = useState(null);
handleFirstConnectivityChange = connectionInfo => {
    setIsOnline(connectionInfo.type !== "none");
  };
useEffect(() => {
    NetInfo.addEventListener("connectionChange", handleFirstConnectivityChange);
return () => {
      NetInfo.removeEventListener(
        "connectionChange",
        handleFirstConnectivityChange
      );
    };
  });
return isOnline;
};

Вы можете получить доступ к этому коду здесь.

Первоначально опубликовано на www.react-native-learner.com 15 февраля 2019 г.