Home > Net >  useEffect run useNavigate when visiting the page
useEffect run useNavigate when visiting the page

Time:11-13

I'm new to React, and I'm trying to make a recpie app with react, right know I want to save the data in json file from the add form. so I can save the data but when I want to redirect the user to the home page using useEffict with navigate. I can't go to the create page when adding navigate to the useEffict.

Create file code:

import { useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useFetch } from "../../hooks/useFetch";

// Styles
import "./Create.css";

export default function Create() {
  const [title, setTitle] = useState("");
  const [method, setMethod] = useState("");
  const [cookingTime, setCookingTime] = useState("");
  const [newIngredient, setNewIngredient] = useState("");
  const [ingredients, setIngredients] = useState([]);
  const { postData, data } = useFetch("http://localhost:3000/recipes", "POST");
  const ingredientsInput = useRef(null);
  const navigate = useNavigate();

  // Methods
  const handleSubmit = (e) => {
    e.preventDefault();
    postData({
      title,
      ingredients,
      method,
      cookingTime: cookingTime   " minutes",
    });
  };

  const handleAdd = (e) => {
    e.preventDefault();
    const ing = newIngredient.trim();

    if (ing && !ingredients.includes(ing)) {
      setIngredients((preIng) => [...preIng, ing]);
    }
    setNewIngredient("");
    ingredientsInput.current.focus();
  };

  useEffect(() => {
    if (data) {
      navigate("/");
      console.log(data);
    }
  }, [data, navigate]);

  return (
    <div className="create">
      <form onSubmit={handleSubmit}>
        <label>
          <span>Recipe Title:</span>
          <input
            type="text"
            onChange={(e) => setTitle(e.target.value)}
            value={title}
            required
          />
        </label>
        <label>
          <span>Recipe ingredients:</span>
          <div className="ingredients">
            <input
              type="text"
              onChange={(e) => setNewIngredient(e.target.value)}
              value={newIngredient}
              ref={ingredientsInput}
            />
            <button onClick={handleAdd} className="btn">
              Add
            </button>
          </div>
        </label>
        {ingredients.length > -1 && (
          <p>
            Current ingredients:{" "}
            {ingredients.map((ing) => (
              <span key={ing}>{ing}, </span>
            ))}
          </p>
        )}
        <label>
          <span>Recipe Method:</span>
          <textarea
            onChange={(e) => setMethod(e.target.value)}
            value={method}
            required
          />
        </label>
        <label>
          <span>Recipe Time (minutes):</span>
          <input
            type="number"
            onChange={(e) => setCookingTime(e.target.value)}
            value={cookingTime}
            required
          />
        </label>
        <button className="btn">Submit</button>
      </form>
    </div>
  );
}

useFetch file code: import { useState, useEffect } from "react";

export const useFetch = (url, method = "GET") => {
  const [data, setData] = useState(null);
  const [isPending, setIsPending] = useState(false);
  const [error, setError] = useState(null);
  const [option, setOption] = useState(null);

  const postData = (data) => {
    setOption({
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data),
    });
  };

  useEffect(() => {
    const controller = new AbortController();

    const fetchData = async (fetchOption) => {
      setIsPending(true);

      try {
        const res = await fetch(url, {
          ...fetchOption,
          signal: controller.signal,
        });
        if (!res.ok) {
          throw new Error(res.statusText);
        }
        const data = await res.json();

        setIsPending(false);
        setData(data);
        setError(null);
      } catch (err) {
        if (err.name === "AbortError") {
          console.log("the fetch was aborted");
        } else {
          setIsPending(false);
          setError("Could not fetch the data");
        }
      }
    };

    if (method === "GET") {
      fetchData();
    }

    if (method === "POST") {
      fetchData(option);
    }

    return () => {
      controller.abort();
    };
  }, [url, option, method]);

  return { data, isPending, error, postData };
};

I don't know from where the issue came.

CodePudding user response:

You basically trying to add a variable that is not a react state variable into the useEffect on update

const [recipes, setReceipies] = useState();

useEffect(async ()=> { const {data} = awawit useFetch("http://localhost:3000/recipes", "POST")
setReceipies(data);
},[])
navigate("/");
},[recipes]);

Or ofc you can navigate all the way from the mounting useEffect

Good Luck

CodePudding user response:

after you save the data, simply add this code

const history = createBrowserHistory()
history.push(`/`)

I have big apps, that use history, and I never had a problem with it.

and I recomend you to use SWR for data-fetching - React Hooks for Data Fetching.

very simple and powerfull tool: https://swr.vercel.app/

  • Related