1

I'm getting proper text from the method loadFIle. But when I try to set the state using setCodeToBeDsiplayed with the returned text, its not getting stored. It is giving empty string in the very next line.

const [CodeToBeDsiplayed, setCodeToBeDsiplayed] = useState("")

const [codeVersion, setCodeVersion] = useState(exampleCodeJava8);

 useEffect( () => {
        (async()=>{
            var text=await loadFile(exampleCodeJava8);
            setCodeToBeDsiplayed(text);
            setCodeVersion(CodeToBeDsiplayed);  
        })()
       
    }, [])

loadFile()

async function loadFile(url) {
        console.log("Dowloading file : " + url);

        return new Promise((resolve,reject)=>{
            var json;
            var xhr = new XMLHttpRequest();
            xhr.responseType = 'text';
                xhr.onload =(event)=>{
                    json = xhr.response;
                    console.log("json : " + json);
                    resolve(json);
                };
                xhr.error=(error)=>{
                    reject(error);
                }
            xhr.open('GET', url);
            xhr.send();
        });
HarshEc
  • 232
  • 8
  • 21
  • of course the variable doesn't change value then and there, the setting of state only takes place on the next render. Just pass in `text` to `setCodeVersion` if that is what you need. – Robin Zigmond Apr 24 '21 at 17:23

3 Answers3

3

useState is an async function and it also does not return a Promise. Using async/await or anything similar will not work. You need to use useEffect and add the dependency to invoke the other state to be set.

useEffect(() => { setCodeVersion(CodeToBeDsiplayed);}, [CodeToBeDsiplayed])
Ayaz
  • 2,111
  • 4
  • 13
  • 16
  • This would make `codeVersion` always equal to `CodeToBeDisplayed` - if this is what is wanted, why have two different state variables at all? – Robin Zigmond Apr 24 '21 at 17:29
3

Michael Parker's answer here should explain where you're going wrong!

From React's documentation:

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

Similarly, when using the useState hook, the updates don't take place immediately but are instead queued and a pending state transition is created.

In your case, you can just use - setCodeVersion(text) to set your state! Hope this helps!

1

you can't get new state value just after setting it as useState is also a asyc function you just have to pass the same text to setcodeversion as of setCodeToBeDsiplayed or you can write like this

const [CodeToBeDsiplayed, setCodeToBeDsiplayed] = useState("")
const [codeVersion, setCodeVersion] = useState(exampleCodeJava8);
useEffect( () => {
    (async()=>{
        var text=await loadFile(exampleCodeJava8);
        setCodeToBeDsiplayed(text=>{
             setCodeVersion(text);
             return text
         });
    })()
   
}, [])
  • This helped me. However I had to add another line of code which was missed by you. Editing the same. – HarshEc Apr 24 '21 at 17:42
  • hey I have seen your suggestion for edit but you don't need to write that line for reference you can visit this link [link](https://reactjs.org/docs/hooks-reference.html#usestate) – Anurag Sharma Apr 24 '21 at 17:53