最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - waiting for useeffect to finish and then accessing object properties - Stack Overflow

programmeradmin5浏览0评论

I have the code below:

const [files, setFiles] = useState([]);
const [greeting, setGreeting] = useState(0);
const [menu, setMenu] = useState([]);
const [options, setOptions] = useState([]);
var customer_id = 1;

useEffect(() => {
    async function getFiles() {
      
      var data = {
        "customer-id": customer_id
      };
      let response = await axios.post(`http://localhost:2000/files/get-files`, data)
      //let response = await axios.post(`/files/get-files`, data)
      for (let i = 0; i < response.data.length; i++) {
        setOptions(oldArray => [...oldArray, {'value': response.data[i]['id'], 'label': response.data[i]['name']}])
      }
      setFiles(response.data)
    }
    async function getIVR() {
      
        var data = {
          "customer-id": customer_id
        };
        let response = await axios.post(`http://localhost:2000/files/get-ivr`, data)
        //let response = await axios.post(`/files/get-ivr`, data)
        
        setGreeting(response.data[0]['greeting'])
        setMenu(response.data[0]['menu'])
    }

    getFiles()
    getIVR() 
}, []);
var test = (options.find(x => x.value === greeting))
console.log(test.get('label'))

The code above returns an error:

TypeError: Cannot read property 'get' of undefined

This is because on first render label does not exist as options is not populated yet. However, when I just console.log(test), I can see that after a few ms it is populated as shown by the logs:

27GreetingMenu.js:53 undefined
GreetingMenu.js:53 undefined
GreetingMenu.js:53 {value: 3, label: "Test Menu"}
GreetingMenu.js:53 {value: 3, label: "Test Menu"}
GreetingMenu.js:53 {value: 3, label: "Test Menu"}
GreetingMenu.js:53 {value: 3, label: "Test Menu"}

How can I make it so that I can always get the value of label. This can be acplished by somehow waiting for useeffect to finish which means options is good which means I can parse it.

Let me know!

I have the code below:

const [files, setFiles] = useState([]);
const [greeting, setGreeting] = useState(0);
const [menu, setMenu] = useState([]);
const [options, setOptions] = useState([]);
var customer_id = 1;

useEffect(() => {
    async function getFiles() {
      
      var data = {
        "customer-id": customer_id
      };
      let response = await axios.post(`http://localhost:2000/files/get-files`, data)
      //let response = await axios.post(`/files/get-files`, data)
      for (let i = 0; i < response.data.length; i++) {
        setOptions(oldArray => [...oldArray, {'value': response.data[i]['id'], 'label': response.data[i]['name']}])
      }
      setFiles(response.data)
    }
    async function getIVR() {
      
        var data = {
          "customer-id": customer_id
        };
        let response = await axios.post(`http://localhost:2000/files/get-ivr`, data)
        //let response = await axios.post(`/files/get-ivr`, data)
        
        setGreeting(response.data[0]['greeting'])
        setMenu(response.data[0]['menu'])
    }

    getFiles()
    getIVR() 
}, []);
var test = (options.find(x => x.value === greeting))
console.log(test.get('label'))

The code above returns an error:

TypeError: Cannot read property 'get' of undefined

This is because on first render label does not exist as options is not populated yet. However, when I just console.log(test), I can see that after a few ms it is populated as shown by the logs:

27GreetingMenu.js:53 undefined
GreetingMenu.js:53 undefined
GreetingMenu.js:53 {value: 3, label: "Test Menu"}
GreetingMenu.js:53 {value: 3, label: "Test Menu"}
GreetingMenu.js:53 {value: 3, label: "Test Menu"}
GreetingMenu.js:53 {value: 3, label: "Test Menu"}

How can I make it so that I can always get the value of label. This can be acplished by somehow waiting for useeffect to finish which means options is good which means I can parse it.

Let me know!

Share Improve this question edited Jul 22, 2021 at 3:01 Brian Thompson 14.4k4 gold badges27 silver badges49 bronze badges asked Jul 21, 2021 at 19:57 JulietteJuliette 4,4393 gold badges19 silver badges41 bronze badges 1
  • Not related to your problem, but is there any reason you have 2 async functions inside your useEffect.? – Keith Commented Jul 21, 2021 at 20:07
Add a ment  | 

2 Answers 2

Reset to default 4

I think you're trying to solve the wrong problem here.

First: This is because on first render label does not exist as options is not populated yet - isn't pletely true. The problem isn't that the label property isn't set, its that test is undefined since find did not get a match.

Instead of trying to wait for a useEffect to plete (you can't directly), you should just do a simple check to make sure test is defined before using it as an object.

var test = (options.find(x => x.value === greeting))

// Easiest solution
console.log(test?.get('label'))

// Without nullsafe operator
console.log(test && test.get('label'))

As a side note, since you may run into this error next: I don't see a get method being added to the objects inside options? So you may get an error next saying .get is not a function.

It looks like maybe you are assuming test will be an Immutable object? But I don't see code anywhere making that the case.

I think you can use useEffect depend on the changes of options and greeting

When options have value, you can get the label

useEffect(()=>{
  if(options && options.length > 0){
    var test = (options.find(x => x.value === greeting));
    console.log(test && test.get('label'));
  }
},[options, greeting]);
发布评论

评论列表(0)

  1. 暂无评论