Home > Enterprise >  React, disable button while http request is being made
React, disable button while http request is being made

Time:06-26

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

  • Related