React useState 和 useEffect 不如预期工作。

huangapple go评论70阅读模式
英文:

React useState and useEffect does not work as expected

问题

我有一个状态用于存储对象和两个useEffect。第一个useEffect仅在首次渲染时执行,而第二个useEffect会在toFetch状态发生变化时执行。此外,toFetch有一个初始值,即安卡拉的坐标,存储在对象中。首先,useEffect用于确定用户是否已授予地理位置权限。如果已经授予权限,它将获取当前位置;如果没有授权,它将不执行任何操作。这时,第二个useEffect生效,基本上从API获取数据并设置"selected"状态。然而,当用户允许地理位置权限时,"selected"状态仍然使用安卡拉的坐标。问题是什么?

以下是您的代码:

function Contex({ children }) {
  let obj = { lat: 39.57, lng: 32.53 }; // 安卡拉的坐标
  const [weather, setWeather] = useState([]);
  const [selected, setSelected] = useState({});
  const [toFetch, settoFetch] = useState(obj);
  const [loading, setloading] = useState(false);

  useEffect(() => {
    const initialSetup = () => {
      const successCallback = (pos) => {
        const {
          coords: { latitude, longitude },
        } = pos;

        settoFetch((prev) => {
          return { type: "single", lat: latitude, lng: longitude };
        });
      };

      const errorCallback = (err) => {};

      navigator.geolocation.getCurrentPosition(successCallback, errorCallback, {
        enableHighAccuracy: true,
      });
    };
    initialSetup();
  }, []);

  useEffect(() => {
    const fetchData = async () => {
      setloading(true);
      let x = toFetch;
      if (toFetch.type === "country") x = await getCountryStates(toFetch.name);
      const weatherData = await dataProvider([x].flat());
      setWeather(weatherData);
      setSelected(weatherData[0]);
      setloading(false);
    };

    fetchData();
  }, [toFetch]);

  return (
    <context.Provider
      value={{
        weather,
        setSelected,
        selected,
        settoFetch,
        loading,
        toFetch,
      }}
    >
      {children}
    </context.Provider>
  );
}

export { Contex, context };

编辑 1:

我尝试过将地理位置作为Promise使用,但也没有成功。请帮助。

英文:

I have one state for storing an object and two useffects. The first useeffect occurs only once in the first render, while the second occurs whenever the 'toFetch' state is changed. In addition, has an initial value for toFetch that is the coordinates of Ankara and is stored in object. First, useffect determines whether the user has granted permission for geolocation. If allowed, it is set to fetch the current location; if it is not, it does nothing. This time, the second useffect works. and basically fetches data from the API and sets the "selected" state. However, when the user allows geolocation, the selected state continues to use Ankara coordinates. What is the problem?

Here is my Code

function Contex({ children }) {
let obj = { lat: 39.57, lng: 32.53 }; // coordinates of ankara
const [weather, setWeather] = useState([]);
const [selected, setSelected] = useState({});
const [toFetch, settoFetch] = useState(obj);
const [loading, setloading] = useState(false);
useEffect(() =&gt; {
const initialSetup = () =&gt; {
const sb = (pos) =&gt; {
const {
coords: { latitude, longitude },
} = pos;
settoFetch((prev) =&gt; {
return { type: &quot;single&quot;, lat: latitude, lng: longitude };
});
};
const eb = (err) =&gt; {};
navigator.geolocation.getCurrentPosition(sb, eb, {
enableHighAccuracy: true,
});
};
initialSetup();
}, []);
useEffect(() =&gt; {
const den = async () =&gt; {
setloading(true);
let x = toFetch;
if (toFetch.type === &quot;country&quot;) x = await getCountryStates(toFetch.name);
const weatherData = await dataProvider([x].flat());
setWeather(weatherData);
setSelected(weatherData[0]);
setloading(false);
};
den();
}, [toFetch]);
return (
&lt;context.Provider
value={{
weather,
setSelected,
selected,
settoFetch,
loading,
toFetch,
}}
&gt;
{children}
&lt;/context.Provider&gt;
);
}
export { Contex, context };

Edit 1:

I tried to use geolocation as promise but it also did not work. Please help

答案1

得分: 1

function Contex({ children }) {
  let obj = { lat: 39.57, lng: 32.53 }; // coordinates of ankara
  const [weather, setWeather] = useState([]);
  const [selected, setSelected] = useState({});
  const [toFetch, settoFetch] = useState(obj);
  const [loading, setloading] = useState(false);

  useEffect(() => {
    const initialSetup = () => {
      const sb = (pos) => {
        const {
          coords: { latitude, longitude },
        } = pos;

        settoFetch((prev) => {
          return { type: "single", lat: latitude, lng: longitude };
        });
      };
      const eb = (err) => {};

      navigator.geolocation.getCurrentPosition(sb, eb, {
        enableHighAccuracy: true,
      });
    };
    initialSetup();
  }, []);

  useEffect(() => {
    const den = async () => {
      setloading(true);
      let x = toFetch;
      if (toFetch.type === "country") x = await getCountryStates(toFetch.name);
      const weatherData = await dataProvider([x].flat());
      setWeather(weatherData);
      setSelected(weatherData[0]);
      setloading(false);
    };

    den();
  }, [toFetch.lat, toFetch.lng]);

  return (
    <context.Provider
      value={{
        weather,
        setSelected,
        selected,
        settoFetch,
        loading,
        toFetch,
      }}
    >
      {children}
    </context.Provider>
  );
}

export { Contex, context };
英文:
function Contex({ children }) {
let obj = { lat: 39.57, lng: 32.53 }; // coordinates of ankara
const [weather, setWeather] = useState([]);
const [selected, setSelected] = useState({});
const [toFetch, settoFetch] = useState(obj);
const [loading, setloading] = useState(false);
useEffect(() =&gt; {
const initialSetup = () =&gt; {
const sb = (pos) =&gt; {
const {
coords: { latitude, longitude },
} = pos;
settoFetch((prev) =&gt; {
return { type: &quot;single&quot;, lat: latitude, lng: longitude };
});
};
const eb = (err) =&gt; {};
navigator.geolocation.getCurrentPosition(sb, eb, {
enableHighAccuracy: true,
});
};
initialSetup();
}, []);
useEffect(() =&gt; {
const den = async () =&gt; {
setloading(true);
let x = toFetch;
if (toFetch.type === &quot;country&quot;) x = await getCountryStates(toFetch.name);
const weatherData = await dataProvider([x].flat());
setWeather(weatherData);
setSelected(weatherData[0]);
setloading(false);
};
den();
}, [toFetch.lat, toFetch.lng]); // Using an object in your useEffect dependency array also causes the infinite loop problem.
return (
&lt;context.Provider
value={{
weather,
setSelected,
selected,
settoFetch,
loading,
toFetch,
}}
&gt;
{children}
&lt;/context.Provider&gt;
);
}
export { Contex, context };

huangapple
  • 本文由 发表于 2023年2月18日 14:44:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75491663.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定