ожидание завершения эффекта использования, а затем доступ к свойствам объекта

#javascript #reactjs #react-hooks #use-effect #use-state

Вопрос:

У меня есть код ниже:

 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'))
 

Приведенный выше код возвращает ошибку:

 TypeError: Cannot read property 'get' of undefined
 

Это связано с тем, что при первом рендеринге метка не существует, так как параметры еще не заполнены. Однако, когда я просто console.log(тест), я вижу, что через несколько мс он заполняется, как показано в журналах:

 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"}
 

Как я могу сделать так, чтобы я всегда мог получить значение метки. Этого можно достичь, каким-то образом дождавшись завершения эффекта использования, что означает, что параметры хороши, а это значит, что я могу их проанализировать.

Дай мне знать!

Комментарии:

1. Не связано с вашей проблемой, но есть ли какая-либо причина, по которой у вас есть 2 асинхронные функции внутри вашего useEffect.?

Ответ №1:

Я думаю, что вы пытаетесь решить здесь неправильную проблему.

Во — первых: Это связано с тем, что при первом рендеринге метка не существует, так как параметры еще не заполнены-это не совсем верно. Проблема не в том, что label свойство не задано, оно test не определено, так find как не получило совпадения.

Вместо того, чтобы пытаться дождаться useEffect завершения a (вы не можете напрямую), вы должны просто выполнить простую проверку, чтобы убедиться test , что он определен, прежде чем использовать его в качестве объекта.

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

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

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

В качестве примечания, поскольку вы можете столкнуться с этой ошибкой в следующем: я не вижу get метода, добавляемого к объектам внутри options ? Таким образом, вы можете получить ошибку, сказав .get , что это не функция.

Похоже, может быть, вы предполагаете test , что это будет неизменяемый объект? Но я нигде не вижу кода, подтверждающего это.

Ответ №2:

Я думаю, что вы можете использовать useEffect в зависимости от изменений options и greeting

Когда параметры имеют значение, вы можете получить метку

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