Soy nuevo en React, así que discúlpeme si este problema es básico para usted.
Básicamente, quiero hacer lo que dice el título,
aquí tengo una función diseñada para este propósito:
function saveAndUpdate() { // data processing and wrap up the finalized data, lets call it newData useEffect(() => { async function loadData() { try { await axios.put(API/updateEntry,{objToUpdate: newData}).then(() => { const { loading, error, data } = axios.get(API/dataForTheTable) callback(data); }); } catch (error) { console.error(error); } } loadData(); }, []); }La devolución de llamada es una función en el componente principal para actualizar el estado relacionado con los datos inmediatamente después de que se actualicen los datos.
const handleCallback = (data) => { setInfo(data); }Y al ejecutar esto, me sale el clásico error que todavía no entiendo del todo:
Error no detectado: Llamada de gancho no válida. Los ganchos solo se pueden llamar dentro del cuerpo de un componente de función. Esto podría suceder por una de las siguientes razones:
Cualquier ayuda será apreciada, ¡gracias!
Parece que lo que estás haciendo es crear un enlace ( saveAndUpdate ) e intentar acceder a él en algún lugar (por ejemplo, dentro de otro enlace o función).
Sin embargo, un gancho para actualizar datos (con axios.put, donde necesita pasar un argumento; los datos para la actualización) no es un buen enfoque, ya que un gancho UseEffect se ejecutará cuando el componente esté montado, no cuando el usuario haga clic. en un botón o lo que sea. Por ejemplo, sería mejor si usa esto para recopilar datos (obtener solicitud) de su backend cuando se monta el componente.
De todos modos, esta es una forma en que puede hacer lo que quiere lograr, usando useCallback. Creé un botón que activa la función y pasa algunos datos (solo puedes ver el comportamiento esperado):
En el gancho saveAndUpdate (nómbralo como useSaveAndUpdate , solo una convención para nombres de ganchos):
import { useEffect, useState } from "react"; export default function useSaveAndUpdate(dataUpdate) { const [data, setData] = useState(null); const [updating, setUpdating] = useState(false); useEffect(() => { if (updating) { const req = function () { // the put request (dataUpdate will be the data we use for the request)... // for this i'm just going to set data to the argument we've passed // the idea is to setData to the returned data from the server setData(dataUpdate); setUpdating(false); // setting updating to false, if there's a re-render it won't do the request again }; req(); } }, [updating, dataUpdate]); return [data, updating, setUpdating]; }En el componente principal:
import { useState, useCallback } from "react"; import useSaveAndUpdate from './useSaveAndUpdate' const parent = () => { const [updateTarget,setUpdateTarget = useState(null) const [data,updating,setUpdating] = useSaveAndUpdate(updateTarget) const updateFunction = useCallback((updateData) => { setUpdating(true) // // ^ Setting updating to true will fire the request inside useSaveAndUpdate when re-render // setUpdateTarget(updateData) // Setting the data for the update (this data will be used in the put request) },[setUpdating,setUpdateTarget]) return ( <h3>{loading?'loading...':'not loading'}</h3> <h3>{data?data.name:'data is null'}</h3> {/*data will be updated when button clicked, so if it's a table just do data.map()...*/} <button onClick={() => updateFunction({name:'jhon'})}>Click me to update</button> ) }Entonces, en el primer renderizado, se mostrará que no se está cargando y que los datos son nulos. Al hacer clic dirá cargando por un segundo (el tiempo que dura la solicitud), y se mostrarán los datos ('jhon').
Una pequeña caja de códigos para que puedas ver cómo funciona .