Siguiente
Cómo usar async/await con axios en reaccionar
Estoy tratando de hacer una solicitud de obtención simple a mi servidor usando Async/Await en una aplicación React.js. El servidor carga un JSON simple en /data que se ve así
JSON
{ id: 1, name: "Aditya" }Puedo obtener los datos en mi aplicación React utilizando el método jquery ajax get simple. Sin embargo, quiero utilizar la biblioteca axios y Async/Await para seguir los estándares ES7. Mi código actual se ve así:
class App extends React.Component{ async getData(){ const res = await axios('/data'); console.log(res.json()); } render(){ return( <div> {this.getData()} </div> ); } }Usando este enfoque me sale el siguiente error:
Los objetos no son válidos como hijos de React (encontrado: [object Promise]). Si tenía la intención de representar una colección de niños, use una matriz en su lugar.
¿No lo estoy implementando correctamente?
Dos cuestiones saltan a la vista:
Su getData nunca devuelve nada, por lo que su promesa (las funciones async siempre devuelven una promesa) se cumplirá con undefined si no se rechaza
El mensaje de error muestra claramente que está tratando de representar directamente la promesa que devuelve getData , en lugar de esperar a que se asiente y luego representar el valor de cumplimiento.
Direccionamiento #1: getData debería devolver el resultado de llamar a json :
async getData(){ const res = await axios('/data'); return await res.json(); }Dirección #2: Tendríamos que ver más de su código, pero fundamentalmente, no puede hacerlo
<SomeElement>{getData()}</SomeElement> ...porque eso no espera a la resolución. En su lugar, necesitaría usar getData para establecer el estado:
this.getData().then(data => this.setState({data})) .catch(err => { /*...handle the error...*/});... y usa ese estado al renderizar:
<SomeElement>{this.state.data}</SomeElement>Actualización : ahora que nos ha mostrado su código, debe hacer algo como esto:
class App extends React.Component{ async getData() { const res = await axios('/data'); return await res.json(); // (Or whatever) } constructor(...args) { super(...args); this.state = {data: null}; } componentDidMount() { if (!this.state.data) { this.getData().then(data => this.setState({data})) .catch(err => { /*...handle the error...*/}); } } render() { return ( <div> {this.state.data ? <em>Loading...</em> : this.state.data} </div> ); } } Actualización adicional: ha indicado una preferencia por usar await en componentDidMount en lugar de then y catch . Haría eso anidando una función IIFE async dentro de ella y asegurándose de que esa función no pueda lanzar. ( componentDidMount en sí mismo no puede ser async , nada consumirá esa promesa). Por ejemplo:
class App extends React.Component{ async getData() { const res = await axios('/data'); return await res.json(); // (Or whatever) } constructor(...args) { super(...args); this.state = {data: null}; } componentDidMount() { if (!this.state.data) { (async () => { try { this.setState({data: await this.getData()}); } catch (e) { //...handle the error... } })(); } } render() { return ( <div> {this.state.data ? <em>Loading...</em> : this.state.data} </div> ); } }En mi experiencia de los últimos meses, me he dado cuenta de que la mejor manera de lograr esto es:
class App extends React.Component{ constructor(){ super(); this.state = { serverResponse: '' } } componentDidMount(){ this.getData(); } async getData(){ const res = await axios.get('url-to-get-the-data'); const { data } = await res; this.setState({serverResponse: data}) } render(){ return( <div> {this.state.serverResponse} </div> ); } } Si está intentando realizar una solicitud de publicación en eventos como hacer clic, llame a la función getData() en el evento y reemplace el contenido de este modo:
async getData(username, password){ const res = await axios.post('url-to-post-the-data', { username, password }); ... } Además, si está realizando alguna solicitud cuando el componente está a punto de cargarse, simplemente reemplace async getData() con async componentDidMount() y cambie la función de procesamiento de la siguiente manera:
render(){ return ( <div>{this.state.serverResponse}</div> ) }Async/Await with axios useEffect(() => { const getData = async () => { await axios.get('your_url') .then(res => { console.log(res) }) .catch(err => { console.log(err) }); } getData() }, [])