• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

219
Views
Gancho de reacción personalizado con efecto de uso, no se puede usar en funciones que no sean componentes

Hice un gancho de reacción personalizado, que tiene un efecto de uso y, por ahora, devuelve un conjunto de estados diferentes. Es un gancho para axios, y la esencia es esta:

 export default function useAxios({ url, data = {}, method = "GET"} ) { var [loading, setLoading] = useState(true) var [data, setData] = useState(null) useEffect(function() { (async function() { // do axios request and set loading and data states })() return () => // cleanup function that cancels axios request }, []) return { loading, data } }

Ahora, en un componente simple, puedo usar fácilmente este gancho personalizado, pero mi pregunta es: ¿Qué pasa si quiero usar mi gancho dentro de un controlador de eventos, digamos:

 export default MyComponent() { function handleSubmit(e) { var { data } = useAxios({ url: "/my-end-point", data: { testInput: e.target.testInput.value } }) } return ( <form onSubmit={handleSubmit}> <input type="text" name="testInput" /> <button type="submit">Submit</button> </form> ) }

El problema es que mi gancho useAxios tiene un efecto de uso, por lo que no puedo usarlo dentro de una función que no sea un componente, es decir, handleSubmit . Entonces, ¿cuál es el trabajo? ¿Hay incluso uno? Gracias por adelantado.

almost 3 years ago · Juan Pablo Isaza
3 answers
Answer question

0

En cuanto a los únicos ganchos de llamada de React desde las funciones de React React siempre debe:

✅ Call Hooks de los componentes de la función React.
✅ Call Hooks desde Hooks personalizados.

Si no se cumplen estas dos reglas, se produce un resultado inesperado de React .

Con esas reglas en mente, debe devolver un submitHanlder desde el enlace de reacción en lugar de simplemente pasar la función de enlace a otro componente como una función de devolución de llamada.

Podría suponer que su intención es activar la solicitud de axios en el evento de envío. Si es así, es posible lograrlo sin pasar todo el gancho al controlador de eventos.

En primer lugar, como dicen las reglas, debes asegurarte de que tu gancho sea llamado en cada renderizado. Entonces MyComponent se puede reescribir de la siguiente manera:

 export default function MyComponent() { var startRequest = useAxios({url: "/my-end-point"}) //<---- useAxios now returns the startRequest function, and will always be called on every render return ( <form onSubmit={(e) => { e.preventDefault() startRequest({testInput: e.target.testInput.value}) // <----- call your startRequest here in the submit hanlder .then(data => { //process your data here }) }}> <input type="text" name="testInput" /> <button type="submit">Submit</button> </form> ) }

Tenga en cuenta que ahora el enlace devuelve una función startRequest que puede colocar en su controlador y activar ese controlador en cualquier momento apropiado.

Y reorganiza el código de tu gancho como se muestra a continuación:

 export function useAxios({ url, method = "GET"} ) { var [loading, setLoading] = useState(true) // <------ no setData here var startRequest = async function(body = {}) { // <------ Move your input here // do axios request and set loading and data states setLoading(true) await data = axios.post(body) setLoading(false) return data // <------- return data as promise } var cancelRequest = () => // cleanup function that cancels axios request useEffect(function() { return cancelRequest }, []) // useEffect only helps your cancel request on unmounted. return startRequest }

El useEffect ahora solo lo ayuda a limpiar la solicitud de axios sin la necesidad de iniciar una, ya que disparar una solicitud debería ser el trabajo de un controlador de eventos.

Y dado que la devolución de datos por parte de axios es una promesa, no necesita setData explícitamente para almacenar sus datos de respuesta, por lo que eliminé la línea de useState(null) .

almost 3 years ago · Juan Pablo Isaza Report

0

Echaría un vistazo a bibliotecas populares como SWR ( useSWR ) y apollo-client ( useQuery) . Su enfoque es algo como esto cuando hacen solicitudes de obtención

 const MyComponent = () => { const [shouldSkip, setShouldSkip] = useState(true); const queryResult = useQuery('my-url', {skip: shouldSkip}); const handleSubmit = () => { setShouldSkip(false); // this will cause the component to rerender, and skip will now be false } }

Al realizar solicitudes de publicación, es algo como esto:

 const MyComponent = () => { //useMutation returns a callable function whenever you want const callFunction = useMutation('my-url'); const handleSubmit = () => { await callFunction() } }

También puede echar un vistazo a los ganchos específicos de axios como https://github.com/simoneb/axios-hooks , otro patrón común que usan es incluir una función de refetch como resultado del gancho, que se puede llamar en cualquier momento (como en un controlador de eventos)

almost 3 years ago · Juan Pablo Isaza Report

0

El objetivo del enlace no es realizar la solicitud por usted, el objetivo del enlace es comunicar el estado interno de las cosas (la solicitud de axios, en su caso) al componente, para que pueda representar las cosas en función de ese estado. (como estados de carga, o los datos).

En su caso, puede cambiar el valor de la consulta según el estado del componente y hacer que el enlace devuelva los datos al componente según sus parámetros. Algo como esto:

 const useAxios = ({ query }) => { var [loading, setLoading] = useState(true) var [data, setData] = useState(null) useEffect(function () { (async function () { setLoading(true) // do axios request and set loading and data states const request = await axios.get('endpoint', { query }) setData(request.data) setLoading(false) })() return () => { }// cleanup function that cancels axios request }, []) return { loading, data } } const Component = () => { const [query, setQuery] = useState('') const { loading, data } = useAxios({ query }); const submitHandler = (event) => { setQuery(event.target.testInput.value) } return ( <> <form onSubmit={submitHandler}> <input name="testInput" /> <input type="submit" /> </form> {loading && ( <>a spinner</> )} {data && ( <DataRenderer data={data} /> )} </> ) }
almost 3 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error