Tengo muchas funciones que se ven así.
doSomething = async (...) => { try { this.setState({loading: true}); ... var result = await Backend.post(...); ... this.setState({loading: false}); } catch(err) { this.setState({error: err}); } }Básicamente, tengo 2 variables de carga y error que debo administrar para muchas funciones y el código es básicamente el mismo para todas ellas. Dado que no hay decoradores en javascript y no deseo instalar ninguna biblioteca experimental para eso, ¿cómo podría envolver esta función para eliminar los setStates duplicados de arriba?
Aquí está mi forma actual, paso la función como parámetro.
Tenemos muchas API, recuperamos datos desde el backend, tenemos que manejar el error y hacer algo con los datos.
Solo los datos de servicio son diferentes, el error de manejo es el mismo.
private processServiceResponse(resp: any, doSthWithData: (data: any) => void) { let { errors } = resp; if (this.hasError(errors)) { this.handleServiceErr(errors); return; } let data = resp; if (resp && resp.data) { data = resp.data; } doSthWithData(data); }Y así es como paso la función como parámetro.
let rest1 = service1.getData(); processServiceResponse(rest1,(data)=>{ //only need to focus with processing data. })PD: Es codificación mecanografiada.
Puede usar una función de orden superior (una función que toma como argumento otra función) para hacer que la funcionalidad común de carga y error sea reutilizable. Es muy similar a un patrón de decorador. Por ejemplo:
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 result; } catch(err) { setState({error: err}); } } }si está utilizando componentes de función, puede definir un enlace personalizado para evitar la repetición del código
//usarFetch.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 && setData(res.data.content); res.content && setData(res.content); }) .catch(err => { setLoading(false) setError('An error occurred. Awkward..') }) return () => { source.cancel(); } }, [url]) return { data, loading, error } export default useFetch;uso:
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 && <p>{loading}</p> } { quote && <p>"{quote}"</p> } { error && <p>{error}</p> } </div> ); } export default App;