Рубрики
Без рубрики

Используйте крючки в классовых компонентах с легкостью

Приложение, которое я развиваю на работе, был в разработке на пару лет, что означает много … Помечено в React, WebDev, JavaScript.

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

Хотя иногда мы хотим включить новые функции для более старых частей приложения. Особенности, которые написаны с крючками.

Без проблем!

Хотя мы не можем использовать крючок внутри компонента класса, мы могли бы использовать один из двух шаблонов для повторного использования кода, который работает с ними: Компоненты высшего порядка и Рендер реквизиты Отказ И сделать крючок доступным через один из них.

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

Мы можем представить себе Usetodos () Крюк, который загружает список TODOS, а может быть, некоторые другие вещи, которые обычно используются так:

function TodosPage() {
   const { data, isLoading, error } = useTodos()
   if(isLoading) return 
   /* etc. */ 
}

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

HOC

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

function injectTodos(Component) {
  const InjectedTodos = function (props) {
    const todos = useTodos(props);
    return ;
  };
  return InjectedTodos;
}

Таким образом, мы просто делаем функцию, она принимает компонент для улучшения со всей информацией Todo. Внутри мы делаем функциональный компонент, который использует крючок и вернуть это.

Мы называем функцию, чтобы сделать INJECTEDTODOS в инструментах DEV вместо того, чтобы просто возвращаться сразу, чтобы облегчить отладку.

Теперь мы могли бы сделать:

class TodosPage extends React.Component {
  render() {
    const { data, isLoading, error } = this.props.todos;
    if(isLoading) return ;
    /* etc. */
  }
}

export default injectTodos(TodosPage);

Здорово!

Теперь, чтобы рендеринг реквизиты

Предполагающий компонент Render Corp в основном угнатит свойства детей, заменяя ее функцией, которая дает вам доступ к дополнительным данным или функциям:

function TodosData({children}) {
  const todos = useTodos()
  return children(todos)
}

И теперь мы могли бы поставить это использовать так:

class TodosPage extends React.Component {
  render() {
    return (
      
        {({isLoading, data, error}) => {
          if(isLoading) return 
          /* etc. */
        }
      
    )
  }
}

До самочувствия

Так что с не так много строк кода мы могли бы сделать крюки доступными в Вы старые Компоненты класса. Но представьте, что у нас есть несколько крючков, которые мы хотели бы сделать доступным. Мы будем вроде писать одни и те же обертки снова и снова и снова, чтобы сделать крючок доступным через рендеринг или HOC.

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

Так что для HOC:

export function makeHOC(useHook, name) {
  return function (Component) {
    const HOC = function (props) {
      const hookData = useHook(props);
      const hookProps = { [name]: hookData }
      return ;
    };

    HOC.displayName = `${name}HOC`;

    return HOC;
  };
}

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

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

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

Теперь, чтобы сделать Hocs наших крючков мы просто делаем это:

const injectTodos = makeHOC(useTodos, "todos")
const injectUsers = makeHOC(useUsers, "users")

А для Render Prop:

export function makeRenderProps(useHook, name) {
  const RenderProps = function ({ children, ...rest }) {
    const hookData = useHook(rest);
    return children(hookData);
  };

  if (name) RenderProps.displayName = `${name}RenderProps`;

  return RenderProps;
}

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

И Создание компонентов рендеринга реквизита:

const TodosData = makeRenderProps(useTodos, "Todos")
const UsersData = makeRenderProps(useUsers, "Users")

Как насчет крючков, которые принимают несколько аргументов?

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

Если бы мы делали Крюк библиотеки реактивных запросов Использование Доступно через HOC или рендеринг реквизиты? Этот крючок нуждается в двух аргументах, идентификатор и функцию, возвращающую обещание данных, а третий, необязательный аргумент параметров.

Таким образом, мы могли бы либо сделать «обертку» крюк, который принимает реквизиты и возвращает крючок с свойствами в нужном месте:

function useWrappedQuery(props) {
  return useQuery(props.queryId, props.queryFn, props.queryOptions)
}

UseWrappywery затем можно использовать нашими Makehoc и MakerenderProops Функции.

Или Makehoc / MakerenderProops Функции могут принять дополнительный, необязательный аргумент. Функция, которая возвращает аргументы крючка. Нравится:

export function makeHOC(useHook, name, convertProps = (props) => [props]) {
  return function (Component) {
    const HOC = function (props) {
      const hookData = useHook(...convertProps(props));
      const hookProps = { [name]: hookData }
      return ;
    };

    HOC.displayName = `${name}HOC`;
    return HOC;
  };
}

ConvertProps Функция должна вернуть массив, который будет распространяться на аргументы в крючке. По умолчанию он вернет массив с реквизитами как первым, и только аргумент. Так же, как предыдущая реализация.

Теперь вы можете сопоставить реквизиты от аргумента HOC/RenderProps крюку:

class TodoList extends React.Component { /*...*/ }

const injectQuery = makeHOC(
  useQuery, 
  "query", 
  props => [
    props.queryKey,
    props.queryFn,
    props.queryOptions
  ]
)

export default injectQuery(TodoList)

И использовать это так, как это

const queryOptions = {retryDelay: 10000}



Теперь Тодолист Компонент имеет данные для крючка, доступные в реквизитах Запрос имущество.

Или Мы могли бы также сложный код аргументов этой функцией:

const injectTodosQuery = makeHOC(
  useQuery,
  "todos",
  () => [
    "todos",
    apiClient.todos.get,
    queryOptions
  ]
}

/* etc. */

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

Фото Marius Niveri. на Бессмысленно

Оригинал: “https://dev.to/stroemdev/use-hooks-in-class-components-with-ease-4io0”