Объяснение того, как и когда использовать React Native Higher Order Components

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

  • Helpers.js
  • Commons.js
  • Utils.js и так далее.

Я решил внести ясность в эту тему и объяснить, как и когда использовать каждый подход наиболее правильным образом. Так что просто следуйте.

Что такое компоненты высшего порядка React?

Компонент высшего порядка (HOC) – это функция, которая принимает компонент и возвращает компонент.

Конкретно компонент более высокого порядка — это функция, которая принимает компонент и возвращает новый компонент.

Какую проблему решает HOC?

Не будем шутить и зададим главный вопрос, какую проблему решают HOC? Зачем нам это нужно?

простой ответ: СУХОЙ, а что такое СУХОЙ, спросите вы? DRY — это принцип, который означает «Не повторяйся».
Я использовал принцип DRY на нескольких языках программирования в течение своей карьеры, и эксперты в отрасли всегда советовали мне это делать.

Например, вызовы API, сложные функции и многое другое.

Так что да, в некоторых случаях вы можете использовать функции Utils для этого, но HOC — это еще одна возможность сделать то же самое и даже больше. Вы можете совместно использовать общие функции, не повторяя один и тот же код, используя HOC.

Расширенный ответ заключается в том, что это нечто большее. Например, с помощью HOC мы можем добавить еще один компонент рядом с исходным компонентом и создать новый компонент, содержащий оба компонента.

Я объясню это следующим вопросом, а что, если мы хотим показать загрузчик при выборке данных по запросу API?

Из этого вопроса мы можем почувствовать силу HOC.

Учитесь на примере

Предположим, что у нас есть следующий компонент.

function ListOfUsers = ()=> {
  const [users, setUsers] = useState([]);
  const [isLoading, setIsLoading] = useState(false);useEffect(()=>{
  (
    async ()=>{
      setIsLoading(true);
      const users = 
         await axios.get(GET_USERS_URL.then(results => results);
      setUsers(users);
      setIsLoading(false);
    }
  )();
  },[])render(
  <View>
    <Loader isLoading={isLoading}/>
    users.length ?
      users.map((user) => <UserCard user={user}/>) :
      <Text>No users</Text>
  </View>
  )
}
export default ListOfUsers;

И теперь мы хотим реализовать подход HOC. Здесь мы можем заметить 2 вещи:

  • Мы делаем запрос на вызов, чтобы получить всех пользователей с сервера.
  • Мы используем компонент Loader.

В этом примере мы можем взять запрос API и компонент Loader из компонента ListOfUsers и переместить их в HOC, этот шаг сделает их повторно используемыми для каждого следующего вызова выборки.

Создание HOC

Теперь давайте создадим HOC. Допустимо вызывать HOC с префиксом with, как в нашем случае withAxiosRequest.

Файл можно создать в «./hoc/withAxiosRequest».

const withAxiosRequest = (OriginalComponent) => {
  return class extends React.Component {
    
    state = { isLoading: false};    createRequest = async (params: {url:string}) => {
      try {
        this.setState({ ...this.state, isLoading: true });        response = await axios.get(params.url).then((res) => res);        this.setState({...this.state, isLoading: false});
       return response;
      } catch (error) {
        this.setState({ ...this.state, isLoading: false });
        return false;
    }
  }  render() {
    return (
    <>
      <Loader isLoading={this.state.isLoading} />
      <OriginalComponent {...this.props}
       createRequest = {this.createRequest}
      />
    </>)
  }
 }
}export default withAxiosRequest;

HOC получает исходный компонент и отправляет обратно новый компонент с большей функциональностью.

Функциональность — это многократно используемая функция createRequest. Теперь каждый раз, когда мы оборачиваем компонент withAxiosRequest HOC, мы можем использовать функцию createRequest.

Обернутый компонент теперь содержит компонент Loader, поэтому любой вызов выборки с createRequest автоматически активирует компонент Loader.

Примечание. Этот пример позволяет вам только извлекать данные, вы можете улучшить эту концепцию HOC, чтобы поддерживать POST, DELETE, PUT и многое другое.

Последний шаг

Последний шаг — обернуть наш компонент ListOfUsers withAxiosRequest HOC.

function ListOfUsers = ({createRequest})=> {
  const [users, setUsers] = useState([]);useEffect(()=>{
  (
    async ()=>{
      const users = await createRequest({url:GET_USERS_URL});
      setUsers(users);
    }
  )();
  },[])render(
  <View>
    users.length ?
      users.map((user) => <UserCard user={user}/>) :
      <Text>No users</Text>
  </View>
  )
}
export default withAxiosRequest(ListOfUsers);

Как видите, мы можем получить функцию createRequest в качестве реквизита в компоненте ListOfUsers, поэтому нам больше не нужен запрос axios в компоненте ListOfUsers.

Наш обернутый компонент теперь содержит компонент Loader по умолчанию, поэтому нам больше не нужен компонент Loader в компоненте ListOfUsers.

Заключение

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

Компоненты высшего порядка делают ваш код более абстрактным, и как только вы освоитесь с ним, вы, возможно, будете использовать этот шаблон слишком часто.

Спасибо за то, что вы дочитали до сих пор, если вам нравится такой контент, и вы хотите поддержать меня как программиста и писателя, чтобы я писал больше статей, подобных этой, пожалуйста, подпишитесь подписаться на Medium (подписка на 5 долларов США в месяц) по моей ссылке, и вы получите неограниченный доступ ко всему на Medium.

Следите за новыми примерами и советами по React Native.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Посетите наш Community Discord и присоединитесь к нашему Коллективу талантов.