Как правильно выполнить логику сразу после того, как setState обновит состояние функционального компонента react?

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

Вопрос:

В настоящее время я создаю страницу профиля, на которой она изначально будет получать сведения о профиле пользователя из конечной точки API. Я хочу, чтобы индикатор загрузки отображал статус выборки. Сейчас я использую хук useState, где я сохраняю логическое значение для состояния загрузки. Однако, прочитав документацию об использовании, он заявил, что она может быть асинхронной. Следовательно, как мне правильно обновить isLoading до true, а затем выполнить логику выборки? Прямо сейчас вот мой фрагмент кода.

 function Profile() {  const [isLoading, setIsLoading] = useState(false);  const [user, setUser] = useState(null);  const { username } = useParams();   const fetchUserDetails = async (username) =gt; {  setIsLoading(true);  try {  const userRes = await API.graphql({  query: queries.getUser,  variables: { username },  });  if (userRes.error) {  throw new Error({ cause: userRes.error });  }  setUser(userRes.data.getUser);  setIsLoading(false);  } catch (error) {  console.error(error);  // push to error page  setIsLoading(false);  }  };   // Fetch user profile data  useEffect(() =gt; {  fetchUserDetails(username);  }, []);  ...  

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

1. Но в таком случае оба являются aysnc, верно? Это означает, что fetchUserDetails может произойти или не произойти после обновления загрузки @AbdulahProho

2. Возможно, поскольку вы запускаете это только на начальном монтировании, isLoading true для начала следует установить значение, затем useEffect выполнить и установить его false по завершении.

3. @pilchard, это сработало бы! Но что, если все наоборот? Как бы вы подошли к такому варианту использования

Ответ №1:

В вашем примере использования вы можете просто установить isLoading значение true изначально и запустить выборку на монтировании.

 function Profile() {  const [isLoading, setIsLoading] = useState(true);  const [user, setUser] = useState(null);  const { username } = useParams();   // Fetch user profile data  useEffect(() =gt; {  const fetchUserDetails = async (username) =gt; {  try {  const userRes = await API.graphql({  query: queries.getUser,  variables: { username },  });  if (userRes.error) {  throw new Error({ cause: userRes.error });  }  setUser(userRes.data.getUser);  setIsLoading(false);  } catch (error) {  console.error(error);  // push to error page  setIsLoading(false);  }  };   fetchUserDetails(username);  }, []);  

но если вы хотите следить за изменениями isLoading , например, для кнопки перезагрузки, вы можете установить ее false изначально, установить значение true в эффекте использования при монтировании и сделать так, чтобы эффект извлечения зависел от isLoading

 function Profile() {  const [isLoading, setIsLoading] = useState(false);  const [user, setUser] = useState(null);  const { username } = useParams();   // set isLoading to true on-mount  useEffect(() =gt; {  setIsLoading(true)  },[]);   // Fetch user profile data  useEffect(() =gt; {  const fetchUserDetails = async (username) =gt; {  try {  const userRes = await API.graphql({  query: queries.getUser,  variables: { username },  });  if (userRes.error) {  throw new Error({ cause: userRes.error });  }  setUser(userRes.data.getUser);  setIsLoading(false);  } catch (error) {  console.error(error);  // push to error page  setIsLoading(false);  }  };   if (isLoading) {  fetchUserDetails(username);  }  }, [isLoading]);   function triggerReload() {  setIsLoading(true)  }  

Ответ №2:

идея состоит в том, чтобы обновить начальную загрузку до true внутри функции выборки, и вы сделали это правильно. чего не хватает, так это добавить, если условие внутри эффекта использования при загрузке верно, а затем получить сведения о пользователе.

 useEffect(() =gt; {  if(isLoading){  fetchUserDetails(username);  } }, [isLoading])  

это приведет к выборке, если условие верно.

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

1. Интересно, что одна из проблем будет заключаться в том, что fetchUserDetails вообще не будет выполняться, возможно, в этом случае, поскольку мое начальное значение isLoading равно false

2. да, fetchUserDetails не будет выполняться, пока условие ложно. вам не нужно, чтобы он выполнялся, так как в нем есть ложные условия, верно?

3. Начальное состояние является ложным