Home > Software engineering >  HTML select tag is not getting populated after fetching the data and changing the state
HTML select tag is not getting populated after fetching the data and changing the state

Time:01-31

I have the following code which should render the dropdown with a list of values once the data is fetched. I used a state value loading to make the re-rendering work.

However, it does not re-render the dropdown after fetching the data. I tried some options which I found on StackOverflow using the useEffect, but it makes my code run into an infinite error loop.

Below is the code:

//necessary imports
function Home(props){
     const [role_options, setRoleOptions] = useState([]) 
     const [is_loading, setIsLoading] = useState(true)
     const set_roles=()=>{        
        let temp_data = []
        Promise.resolve(get_roles()).then(value=>{ 
        value.map((x,i)=>{
        let eachx = {key:i,text:x,value:x}
        temp_data.push(eachx)})                
       })      
       return temp_data    
       }
      useEffect(()=>{
        setRoleOptions(set_roles());   
        setIsLoading(false) ;
      },[])   
      if(is_loading === true)
         return ('Loading......')
      return(
          <ul className="dropdown-menu">
             {role_options.map((role,i)=>{
                 <li key={role.key}>{role.text} {role.value}</li>
              })}
         </ul>
      )
}
export default Home

I would also like to add that the above code works if I just change the <ul>, <li> to Dropdown from semantic-ui-react. I have also tried <select>, <option> HTML tags that also do not work. If I add role_options as a dependency inside the useEffect like below:

useEffect(()=>{
    setRoleOptions(set_roles());   
    setIsLoading(false) ;
  },[role_options]) 

This makes my code run into an infinite loop. Could anyone please tell me what will be the solution to what I am doing wrong here?

Also, this component is called in the App.js file of React as one of the many components, and this Home component is the first one which is called when the page loads after npm start.

CodePudding user response:

Use your useEffect like below, with an empty dependency array. I assume get_roles is an asynchronous function, according to how you used it.

function Home(props) {
  const [role_options, setRoleOptions] = useState([]);
  const [is_loading, setIsLoading] = useState(true);

  useEffect(() => {
    get_roles().then((value) => {
      const temp_data = value.map((x, i) => ({ key: i, text: x, value: x }));
      setRoleOptions(temp_data);
      setIsLoading(false);
    });
  }, []);

  if (is_loading === true) return "Loading......";
  return (
    <ul className="dropdown-menu">
      {role_options.map((role, i) => {
        return (
          <li key={role.key}>
            {role.text} {role.value}
          </li>
        );
      })}
    </ul>
  );
}
export default Home;

Your attempt is not working because temp_data is returned before the promise is resolved. And another error, you are not returning anything in your map.

  • Related