I am working with React on implementing a in-table button which runs an http request to decide whether to disable, something like:
<Table>
<tbody>
<tr>
<td>something1</td>
<td>something2</td>
<td>something3</td>
<Button onClick = {() => DoSomething()} disabled=
{Boolean(HTTPRequest(payload))}>
Click me!
</Button>
</tr>
</tbody>
</Table>
function HTTPRequest(payload) {
const {loading, error, data} = axios.get(API)
return data.length > 0
}
However, I notice that this does not work since the function is done before receiving a real result. I thought it has something to do with asynchrony, so I changed it to:
async function HTTPRequest(payload) {
const {loading, error, data} = await axios.get(API)
return data.length > 0
}
But it still does not work. Any suggestions will be appreciated, thank you!
CodePudding user response:
As you did, you would need a state that's outside of HTTPRequest
function. Something like this:
const [loading, setLoading] = useState(false);
async function HTTPRequest(payload) {
setLoading(true);
const {loading, error, data} = await axios.get(API)
setLoading(false);
}
<Button onClick = {() => DoSomething()} disabled={loading}>
Click me!
</Button>
CodePudding user response:
"disabled" attribute no supposed to execute a function.
You need to execute the function on the component mount and add state to update the UI.
Ex;
const [disabled, setDisabled] = useState(false);
async function HTTPRequest(payload) {
const {loading, error, data} = await axios.get(API)
setDisabled(data.length > 0)
}
useEffect(() => {(async () => await HTTPRequest())()}, [])
CodePudding user response:
I think the way to go is to use a state and an effect.
const [bool, setBool] = useState(initialBoolStateWanted);
useEffect(()=>{
(async()=>{
let data = await axios.get(API)
setBool(data.length > 0)
})()
},[])
return(
<Button onClick = {() => DoSomething()} disabled={bool}>
Click me!
</Button>
)
Edit: Added to solution to comment
If you need to make several requests
const [bools, setBools] = useState([initialBoolStateWanted]);
useEffect(()=>{
(async()=>{
let datas = await Promise.all(
//For each button give different props to the request
bools.map((elem, index) => axios.get(API(index))
)
setBools(datas.map(elem => elem.length > 0))
})()
},[])
return(
<Button onClick = {() => DoSomething()} disabled={bool}>
Click me!
</Button>
)
If you can do it in a single request which return an array
const [bools, setBools] = useState([initialBoolStateWanted]);
useEffect(()=>{
(async()=>{
let datas = await axios.get(API)
setBools(datas.map(elem => elem.length > 0))
})()
},[])
return(
<Button onClick = {() => DoSomething()} disabled={bool}>
Click me!
</Button>
)
Or make a button component that handles it's own state