• 13-01-2023, 19:25:36
    #1
    Merhaba,
    axios la API den veri çekiyorum bunun için de async kullanıyorum ki return edildiği zaman veriler gelsin. Ama finally bloğunda kontrol ettiğim zaman veri(details.id mesela) hala gelmemiş oluyor. Ama En aşağıda return kısmındaki DisplayRecipe componentinde kontrol ettiğimde veri gelmiş oluyor ama iş işten geçmiş oluyor çünkü boş veri return edilmiş oluyor zaten ya da koşul belirtmesem bir önceki veri ekrana geliyor.
    Sorun nerede sizce?
    23 ve 59. satırlar

    function Recipe() {
      const [details, setDetails] = useState([]);
      const [activeTabs, setActiveTabs] = useState("ingredients");
      const [isLoading, setIsLoading] = useState(false);
      const params = useParams();
      let isMounted = null;
      useEffect(() => {
        isMounted=true;
        const source = axios.CancelToken.source();
        const getDetails = async () => {
      
          const options = {
            method: "GET",
            url:`https://${process.env.REACT_APP_MEAL_RECIPE_API_HOST}/recipe/${params.id}`,
            headers: {
              "X-RapidAPI-Key": process.env.REACT_APP_MEAL_RECIPE_API_KEY,
              "X-RapidAPI-Host": "food-recipe-api.p.rapidapi.com",
            },
            cancelToken: source.token,
          };
      
            setIsLoading(true);
            try {
               await axios.request(options).then((response)=> response.data[0]
              ).then((res)=>{
                if (isMounted) {
                  setDetails(res);
                   console.log(details)
                 }
              })
              
            } catch (err) {
              if (isMounted) {
                setDetails([]);
                 console.log(err.message)
              }
            } finally {
               setIsLoading(false);
               console.log('params id: '+params.id+ ' details id: '+details.id)
            }
      
            const cleanUp = ()=>{
              isMounted=false;
              source.cancel();
              
            }
            return cleanUp;
          
          
        }
        getDetails();
      
      }, [params.id]);
    
      
      return (
        <DetailWrapper>
          {isLoading && <p>...Loading</p>}
          {!isLoading &&  details.id==params.id && <DisplayRecipe params={params.id} details={details} activeTabs={activeTabs} setActiveTabs={setActiveTabs} Button={Button}/>}
        </DetailWrapper>
      );
    }
  • 13-01-2023, 19:43:40
    #2
    Try..catch blokları asenkron değildir. Aynı mantığı asenkron olarak yazmak için promise fonksiyonunuza chaining yapmalısınız. Asenkron axios isteğini awaitle beklemenize gerek kalmadan axios.request() fonsiyonunda yaptığınız işlemin sonuna .catch() ekleyerek sardığınız catch bloğunun görevini, .finally() ekleyerek de finally bloğunda yapmak istediğinizi yapmış olacaksınız.
    https://developer.mozilla.org/en-US/.../Promise/catch
    https://developer.mozilla.org/en-US/...romise/finally
    Ama size önerim hazır öğreniyoken direk data fetching'i tanstack react query ile öğrenin daha az kod yazarak daha okunabilir daha sağlam kod yazmış olursunuz.
  • 13-01-2023, 19:52:15
    #3
    OrhanCekic adlı üyeden alıntı: mesajı görüntüle
    Try..catch blokları asenkron değildir. Aynı mantığı asenkron olarak yazmak için promise fonksiyonunuza chaining yapmalısınız. Asenkron axios isteğini awaitle beklemenize gerek kalmadan axios.request() fonsiyonunda yaptığınız işlemin sonuna .catch() ekleyerek sardığınız catch bloğunun görevini, .finally() ekleyerek de finally bloğunda yapmak istediğinizi yapmış olacaksınız.
    https://developer.mozilla.org/en-US/.../Promise/catch
    https://developer.mozilla.org/en-US/...romise/finally
    Ama size önerim hazır öğreniyoken direk data fetching'i tanstack react query ile öğrenin daha az kod yazarak daha okunabilir daha sağlam kod yazmış olursunuz.
    Aslında aşağıda ilk başta böyle yapmıştım ama bu da çalışmamıştı, o yüzden axios ile en son yaptım
    onst getDetails = async () => {
        setIsLoading(true);
        setDetails([]);
      
        const options = {
          method: "GET",
          headers: {
            "X-RapidAPI-Key": process.env.REACT_APP_MEAL_RECIPE_API_KEY,
            "X-RapidAPI-Host": "food-recipe-api.p.rapidapi.com",
          },
        };
        await fetch(
          `https://${process.env.REACT_APP_MEAL_RECIPE_API_HOST}/recipe/${params.id}`,
          options, { signal: controller.signal }
        )
          .then((response) => response.json())
          .then((response) => {
             setDetails(response[0]);
            console.log(response[0]);
             console.log(params.id)
          }).then(()=> {
          setIsLoading(false)
         })
      };
      useEffect(() => {
        getDetails();
        controller.abort()
      }, [params.id]);
  • 13-01-2023, 20:06:06
    #4
    react query kullandığınızda da zaten axios kullanacaksınız ama daha düzenli şekilde bu şekilde değil. önce react render mantığı ve useEffect'in mantığını kavramanız gerekiyor. Data loading state'te mi error mu oldu, kullanıcının interneti mi dalgalandı tüm bu senaryoları etkili şekilde karşılayamayız. Bu tarz durumları librarylere bırakmak gerekiyor.
    https://tanstack.com/query/v4/docs/react/overview
  • 29-01-2023, 14:47:44
    #5
    Sorun, setDetails(res) fonksiyonunun asenkron bir şekilde çalıştığı ve console.log(details) ve console.log('params id: '+params.id+ ' details id: '+details.id) komutlarının içinde bulunan kontrol işlemlerinin gerçekleştirilmeden önce çalışmasından kaynaklanıyor. Yani, bu komutlar çalıştığında state hala güncellenmemiş olabilir ve bu nedenle beklenen değerleri döndüremeyebilir. Bu problemi çözmek için, setDetails fonksiyonunun callback fonksiyonunda kontrol işlemlerini gerçekleştirmeniz gerekir.