3

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!

0

3 Answers 3

3

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 its own state

Sign up to request clarification or add additional context in comments.

Comments

2

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>

Comments

1

"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())()}, [])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.