Как мне обернуть методы в компоненты react

#javascript #reactjs #wrapper

Вопрос:

У меня есть много функций, которые выглядят так

   doSomething = async (...) => {
    try {
      this.setState({loading: true});

      ...
      var result = await Backend.post(...);
      ...

      this.setState({loading: false});
    } catch(err) {
      this.setState({error: err});
    }
  }
 

В основном у меня есть 2 переменные загрузки и ошибки, которыми я должен управлять для многих функций, и код в основном одинаков для всех из них. Поскольку в javascript нет декораторов, и я не хочу устанавливать для этого какую-либо экспериментальную библиотеку, как я мог бы обернуть эту функцию, чтобы удалить дублированные состояния набора сверху ?

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

1. Почему бы просто не извлечь его в метод, чтобы вы сделали, например doSomething = this.manageLoading(async () => { var result = await Backend.post(...); ... }) .

Ответ №1:

Вот мой текущий способ, я передаю функцию в качестве параметра.

У нас много API, бэкэнд для извлечения данных, мы должны обрабатывать ошибки и что-то делать с данными.

Различаются только данные службы, ошибка обработки одна и та же.

 private processServiceResponse(resp: any, doSthWithData: (data: any) => void) {
    let { errors } = resp;
    if (this.hasError(errors)) {
      this.handleServiceErr(errors);
      return;
    }
    let data = resp;
    if (resp amp;amp; resp.data) {
      data = resp.data;
    }
    doSthWithData(data);
  }
 

И вот как я передаю функцию в качестве параметра.

 let rest1 = service1.getData();
processServiceResponse(rest1,(data)=>{
//only need to focus with processing data.
})
 

PS: Это кодировка машинописного текста.

Ответ №2:

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

//useFetch.js

 import { useState, useEffect } from 'react';
import axios from 'axios';

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
      setLoading('loading...')
      setData(null);
      setError(null);
      const source = axios.CancelToken.source();
      axios.get(url, { cancelToken: source.token })
      .then(res => {
          setLoading(false);
          //checking for multiple responses for more flexibility 
          //with the url we send in.
          res.data.content amp;amp; setData(res.data.content);
          res.content amp;amp; setData(res.content);
      })
      .catch(err => {
          setLoading(false)
          setError('An error occurred. Awkward..')
  })
      return () => {
          source.cancel();
      }
  }, [url])

   return { data, loading, error }

export default useFetch;
 

использование:

 import useFetch from './useFetch';
import './App.css';

function App() {
  const { data: quote, loading, error } = 
useFetch('https://api.quotable.io/random')

  return (
    <div className="App">
      { loading amp;amp; <p>{loading}</p> }
      { quote amp;amp; <p>"{quote}"</p> }
      { error amp;amp; <p>{error}</p> }
    </div>
  );
}

export default App;
 

Ответ №3:

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

 const doSomething = withLoadingAndErrorHandling(Backend.post, this.setState);


function withLoadingAndErrorHandling(fn, setState) {
    return async function(...args) {
       try {
          setState({loading: true});
          var result = await fn(args); 
          setState({loading: false});
          return resu<
        } catch(err) {
          setState({error: err});
        }
    }

}