I have a react controler that call a endpoint. When I get the response I display the information in an object and I want to change a color of a buton to represent if the response was a 200 or a 404.
import React, { useState, useEffect } from "react";
import "./../App.css";
import axios from "axios";
const MicroService = (props) => {
const [personsGet, setPersonGet] = useState([]);
function llamadaAxiosGet (url) {
axios
.get(url)
.then((res) => {
setPersonGet(res.data);
return res.status;
})
.catch(function (error) {
return error.status;
});
}
return (
<div>
<h2>Microservicio:</h2>
<BotonLlamada
url={`https://jsonplaceholder.typicode.com/users`}
textBoton={"Llamada al servicio y display all"}
llamadaAxiosGet={llamadaAxiosGet}
/>
{personsGet.map((person) => (
<li key={person.name}>{person.name}</li>
))}
</div>
);
};
function BotonLlamada(props) {
const [colorButon, setColorButon] = useState("");
const [estado , setEstado]= useState(0);
const onClickbuton = () => {
setEstado(props.llamadaAxiosGet(props.url));
setEstado(props.llamada);
if (estado === 200) {
setColorButon("buttonGreen");
} else if (estado > 399) {
setColorButon("buttonRed");
}
};
useEffect(() => {
if (estado > 399) {
setColorButon("buttonRed");
} else if (estado === 200) {
setColorButon("buttonGreen");
}
},[estado]);
return (
<div>
<button onClick={onClickbuton} className={colorButon}>
{props.textBoton}
</button>
<br />
</div>
);
}
export default MicroService;
So in the code, because axios is async, this will receive the response after finish the method onClick in the buton but the buton won't change color. Can someone helps?
I think that you shold move the llamadaAxiosGet function call in the BotonLlamada component and pass the setPersonGet state property to it:
const MicroService = (props) => {
const [personsGet, setPersonGet] = useState([]);
return (
<div>
<h2>Microservicio:</h2>
<BotonLlamada
textBoton={"Llamada al servicio y display all"}
setPersonGet={setPersonGet}
/>
{personsGet.map((person) => (
<li key={person.name}>{person.name}</li>
))}
</div>
);
};
function BotonLlamada(props) {
const [colorButon, setColorButon] = useState("");
const [estado , setEstado]= useState(0);
function llamadaAxiosGet () {
axios
.get(`https://jsonplaceholder.typicode.com/users`)
.then((res) => {
props.setPersonGet(res.data);
setEstado(res.status);
setColorButon("buttonGreen");
})
.catch(function (error) {
setEstado(error.status);
setColorButon("buttonRed");
});
}
useEffect(() => {
if (estado > 399) {
setColorButon("buttonRed");
} else if (estado === 200) {
setColorButon("buttonGreen");
}
},[estado]);
return (
<div>
<button onClick={() => llamadaAxiosGet() } className={colorButon}>
{props.textBoton}
</button>
<br />
</div>
);
}
export default MicroService;
Your issue is that you're setting your state to a promise of number.
A simple fix would be:
const onClickbuton = () => {
props.llamadaAxiosGet(props.url)
.then(status => setEstado(status));
};
You could also refactor and shift your logic up to the parent component.
import React, { useState } from "react";
import "./../App.css";
import axios from "axios";
function BotonLlamada({ colour, onClick, textBoton }) {
return (
<div>
<button onClick={onClick} className={colour}>
{textBoton}
</button>
<br />
</div>
);
}
const MicroService = (props) => {
const [personsGet, setPersonGet] = useState([]);
const [colour, setColour] = useState("");
function llamadaAxiosGet(url) {
axios
.get(url)
.then((res) => {
setPersonGet(res.data);
return res.status;
})
.catch(function (error) {
return error.status;
})
.then((status) => {
if (status > 399) {
setColour("buttonRed");
} else if (status === 200) {
setColour("buttonGreen");
}
});
}
return (
<div>
<h2>Microservicio:</h2>
<BotonLlamada
textBoton={"Llamada al servicio y display all"}
onClick={() =>
llamadaAxiosGet(`https://jsonplaceholder.typicode.com/users`)
}
colour={colour}
/>
{personsGet.map((person) => (
<li key={person.name}>{person.name}</li>
))}
</div>
);
};
export default MicroService;