Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react select load async options does not load

I want to load options from backend. So i have to fetch data from API and then update options. But i don't know how to do it. Can someone help? Here's my code:

function myComponent() {

  const loadOptions = () => {
    console.log('on load options function')
    axios.get(`/api/admin/roles`)
      .then((response) => {
        const options = []
        response.data.permissions.forEach((permission) => {
          options.push({
            label: permission.name,
            value: permission.id
          })
        })
        return options
      })
  }

  return ( 
    <AsyncSelect 
      isMulti 
      cacheOptions 
      loadOptions={loadOptions}
    />
  )
}

By the way nothing gets logged at all and that means the loadOptions function does not run. Here's my response from API:

response: {
  data: {
    permissions: [{
      id: 13,
      name: 'deposit'
    }, {
      id: 14,
      name: 'withdraw'
    }]
  }
}
like image 825
Ardalan Avatar asked Sep 03 '25 03:09

Ardalan


2 Answers

The issue you're experiencing seems to be due to the fact that you're not returning anything at the top-level of the loadOptions function.

The documentation highlights two ways to define your loadOptions function.

Using callbacks:

const loadOptions = (inputValue, callback) => {
  setTimeout(() => {
    callback(options);
  }, 1000);
};

Using promises:

const loadOptions = inputValue =>
  new Promise(resolve => {
    setTimeout(() => {
      resolve(options);
    }, 1000);
  });

In your case, it might be simplest to try the callback option first since your existing syntax is conducive with it.

const loadOptions = (inputValue, callback) => {
  console.log('on load options function')
  axios.get(`/api/admin/roles`)
    .then((response) => {
      const options = []
      response.data.permissions.forEach((permission) => {
        options.push({
          label: permission.name,
          value: permission.id
        })
      })
      callback(options);
    })
}

In the future you can optionally leverage the inputValues parameter to down-filter results.

like image 163
Seth Avatar answered Sep 05 '25 18:09

Seth


Your loadOptions function must return a promise. Also you can pass defaultOptions as true to make the request fire for initial set of options

const loadOptions = () => {
    console.log('on load options function')
    return axios.get(`/api/admin/roles`)
      .then((response) => {
        const options = []
        response.data.permissions.forEach((permission) => {
          options.push({
            label: permission.name,
            value: permission.id
          })
        })
        return options
      })
  }

function myComponent() {
  return ( 
    <AsyncSelect 
      isMulti 
      cacheOptions 
      defaultOptions
      loadOptions={loadOptions}
    />
  )
}

P.S For performance reasons, you can declare your loadOptions function outside of the component so that it doesn't get recreated on every re-render

like image 30
Shubham Khatri Avatar answered Sep 05 '25 18:09

Shubham Khatri