反应功能组件获取数据时 setHooks 的奇怪行为
react functional component Strange behavior of setHooks when I fetch data
我有一个 React class 完成了我需要的工作,我不得不将它更改为功能组件以使用 useLocation()。
事实证明,通过切换到功能组件,我的状态更新不再正常工作。
我的函数是这样的形式
import * as React from "react";
import { useEffect, useState } from "react";
import Axios from "axios";
import { useLocation } from "react-router-dom";
const URL = `my-path`;
const Sessions: React.FC<{ loadingParam?: boolean | undefined, someBooleanParam?: boolean | undefined, data?: AnyType[] | undefined }> = ({ loadingParam = true, someBooleanParam = undefined, data = undefined}) => {
const [loading, setLoading] = useState(loadingParam);
const [someBoolean, setSomeBoolean] = useState(someBooleanParam);
const [dataFetch, setDataFetch] = useState(data);
const location:any = useLocation();
useEffect(() =>
{
if(location.state == null){
console.log("first implementation");
} else {
const dataToFill:AnyType[]|undefined = location.state.data;
if( data ) {
setDataFetch(dataToFill);
setLoading(false);
setSomeBoolean(undefined);
}
}
}
,
[setDataFetch, setLoading, setSomeBoolean]
);
async function fetchData() {
try {
setLoading(true);
await Axios.get<AnyType[]>(URL)
.then(res => {
if (res.status === 200 && res != null) {
console.log("1 ", dataFetch); //undefined
console.log("1 bis ", res.data); //the data I want in the form I want
var copy:AnyType[] = [...res.data];
setDataFetch([...res.data]);
console.log("2 ", dataFetch); //undefined
console.log("2 ter ", copy); //the data I want in the form I want
setDataFetch(copy);
console.log("2 ", dataFetch); //undefined
setLoading(false);
if (dataFetch?.length === parseInt(someValue)){
setSomeBoolean(true);
} else {
setSomeBoolean(false);
}
} else {
console.log('problem when fetching the data from backend');
}
})
.catch(error => {
console.log(error);
});
}
catch (exception) {
console.log(exception);
}
}
console.log("8 ", dataFetch); //Appears in the web console several times during the execution of the fetchData function with the data I want
return(
<div className="container">
<div>
<button onClick={fetchData}> Click to get data </button>
</div>
{(someBoolean == true && loading == false) ?
Some Action
: <></>
</div>
);
}
export default Sessions;
在这段代码中,在 fetchData 函数中,我需要知道 dataFetch 数组的大小来设置 someBoolean 的值,但是在 运行 时,try 块中没有定义 dataFetch。但是当我在同一个函数中创建一个副本时,它定义得很好,我不明白。
我还尝试将对 Axios 的调用放入返回承诺的异步函数中,从而从我的 fetchData 函数中获取它,但它给了我类似的结果。
我还尝试在没有 try/catch 块的情况下使 fetchData 函数成为非异步的,但结果仍然相同。
我需要的是在 fetchData 函数中,在 .then 块中,流程停止填充我的 dataFetch,然后检查数组的大小,然后呈现我的组件。但我不想设置 setTimeout,因为我认为这是一种过于静态的行为。还有其他方法吗?
有没有人看到我在解释此行为的代码中做错了什么?
提前感谢任何愿意花时间帮助我的人
一种方法是将 setSomeBoolean
部分放入另一个 useEffect
中,该部分在 dataFetch
更改时运行。类似的东西:
import * as React from "react";
import { useEffect, useState } from "react";
import Axios from "axios";
import { useLocation } from "react-router-dom";
const URL = `my-path`;
const Sessions: React.FC<{ loadingParam?: boolean | undefined, someBooleanParam?: boolean | undefined, data?: AnyType[] | undefined }> = ({ loadingParam = true, someBooleanParam = undefined, data = undefined}) => {
const [loading, setLoading] = useState(loadingParam);
const [someBoolean, setSomeBoolean] = useState(someBooleanParam);
const [dataFetch, setDataFetch] = useState(data);
const location:any = useLocation();
useEffect(() =>
{
if(location.state == null){
console.log("first implementation");
} else {
const dataToFill:AnyType[]|undefined = location.state.data;
if( data ) {
setDataFetch(dataToFill);
setLoading(false);
setSomeBoolean(undefined);
}
}
}
,
[setDataFetch, setLoading, setSomeBoolean]
);
useEffect(()=>{
if (dataFetch?.length === parseInt(someValue)){
setSomeBoolean(true);
} else {
setSomeBoolean(false);
}
setLoading(false);
},[dataFetch])
async function fetchData() {
try {
setLoading(true);
await Axios.get<AnyType[]>(URL)
.then(res => {
if (res.status === 200 && res != null) {
console.log("1 ", dataFetch); //undefined
console.log("1 bis ", res.data); //the data I want in the form I want
var copy:AnyType[] = [...res.data];
setDataFetch([...res.data]);
console.log("2 ", dataFetch); //undefined
console.log("2 ter ", copy); //the data I want in the form I want
setDataFetch(copy);
console.log("2 ", dataFetch); //undefined
} else {
console.log('problem when fetching the data from backend');
}
})
.catch(error => {
console.log(error);
});
}
catch (exception) {
console.log(exception);
}
}
console.log("8 ", dataFetch); //Appears in the web console several times during the execution of the fetchData function with the data I want
return(
<div className="container">
<div>
<button onClick={fetchData}> Click to get data </button>
</div>
{(someBoolean == true && loading == false) ?
Some Action
: <></>
</div>
);
}
export default Sessions;
我也不确定你为什么要 [setDataFetch, setLoading, setSomeBoolean]
作为第一个 useEffect
的依赖数组?
我有一个 React class 完成了我需要的工作,我不得不将它更改为功能组件以使用 useLocation()。
事实证明,通过切换到功能组件,我的状态更新不再正常工作。
我的函数是这样的形式
import * as React from "react";
import { useEffect, useState } from "react";
import Axios from "axios";
import { useLocation } from "react-router-dom";
const URL = `my-path`;
const Sessions: React.FC<{ loadingParam?: boolean | undefined, someBooleanParam?: boolean | undefined, data?: AnyType[] | undefined }> = ({ loadingParam = true, someBooleanParam = undefined, data = undefined}) => {
const [loading, setLoading] = useState(loadingParam);
const [someBoolean, setSomeBoolean] = useState(someBooleanParam);
const [dataFetch, setDataFetch] = useState(data);
const location:any = useLocation();
useEffect(() =>
{
if(location.state == null){
console.log("first implementation");
} else {
const dataToFill:AnyType[]|undefined = location.state.data;
if( data ) {
setDataFetch(dataToFill);
setLoading(false);
setSomeBoolean(undefined);
}
}
}
,
[setDataFetch, setLoading, setSomeBoolean]
);
async function fetchData() {
try {
setLoading(true);
await Axios.get<AnyType[]>(URL)
.then(res => {
if (res.status === 200 && res != null) {
console.log("1 ", dataFetch); //undefined
console.log("1 bis ", res.data); //the data I want in the form I want
var copy:AnyType[] = [...res.data];
setDataFetch([...res.data]);
console.log("2 ", dataFetch); //undefined
console.log("2 ter ", copy); //the data I want in the form I want
setDataFetch(copy);
console.log("2 ", dataFetch); //undefined
setLoading(false);
if (dataFetch?.length === parseInt(someValue)){
setSomeBoolean(true);
} else {
setSomeBoolean(false);
}
} else {
console.log('problem when fetching the data from backend');
}
})
.catch(error => {
console.log(error);
});
}
catch (exception) {
console.log(exception);
}
}
console.log("8 ", dataFetch); //Appears in the web console several times during the execution of the fetchData function with the data I want
return(
<div className="container">
<div>
<button onClick={fetchData}> Click to get data </button>
</div>
{(someBoolean == true && loading == false) ?
Some Action
: <></>
</div>
);
}
export default Sessions;
在这段代码中,在 fetchData 函数中,我需要知道 dataFetch 数组的大小来设置 someBoolean 的值,但是在 运行 时,try 块中没有定义 dataFetch。但是当我在同一个函数中创建一个副本时,它定义得很好,我不明白。
我还尝试将对 Axios 的调用放入返回承诺的异步函数中,从而从我的 fetchData 函数中获取它,但它给了我类似的结果。
我还尝试在没有 try/catch 块的情况下使 fetchData 函数成为非异步的,但结果仍然相同。
我需要的是在 fetchData 函数中,在 .then 块中,流程停止填充我的 dataFetch,然后检查数组的大小,然后呈现我的组件。但我不想设置 setTimeout,因为我认为这是一种过于静态的行为。还有其他方法吗?
有没有人看到我在解释此行为的代码中做错了什么?
提前感谢任何愿意花时间帮助我的人
一种方法是将 setSomeBoolean
部分放入另一个 useEffect
中,该部分在 dataFetch
更改时运行。类似的东西:
import * as React from "react";
import { useEffect, useState } from "react";
import Axios from "axios";
import { useLocation } from "react-router-dom";
const URL = `my-path`;
const Sessions: React.FC<{ loadingParam?: boolean | undefined, someBooleanParam?: boolean | undefined, data?: AnyType[] | undefined }> = ({ loadingParam = true, someBooleanParam = undefined, data = undefined}) => {
const [loading, setLoading] = useState(loadingParam);
const [someBoolean, setSomeBoolean] = useState(someBooleanParam);
const [dataFetch, setDataFetch] = useState(data);
const location:any = useLocation();
useEffect(() =>
{
if(location.state == null){
console.log("first implementation");
} else {
const dataToFill:AnyType[]|undefined = location.state.data;
if( data ) {
setDataFetch(dataToFill);
setLoading(false);
setSomeBoolean(undefined);
}
}
}
,
[setDataFetch, setLoading, setSomeBoolean]
);
useEffect(()=>{
if (dataFetch?.length === parseInt(someValue)){
setSomeBoolean(true);
} else {
setSomeBoolean(false);
}
setLoading(false);
},[dataFetch])
async function fetchData() {
try {
setLoading(true);
await Axios.get<AnyType[]>(URL)
.then(res => {
if (res.status === 200 && res != null) {
console.log("1 ", dataFetch); //undefined
console.log("1 bis ", res.data); //the data I want in the form I want
var copy:AnyType[] = [...res.data];
setDataFetch([...res.data]);
console.log("2 ", dataFetch); //undefined
console.log("2 ter ", copy); //the data I want in the form I want
setDataFetch(copy);
console.log("2 ", dataFetch); //undefined
} else {
console.log('problem when fetching the data from backend');
}
})
.catch(error => {
console.log(error);
});
}
catch (exception) {
console.log(exception);
}
}
console.log("8 ", dataFetch); //Appears in the web console several times during the execution of the fetchData function with the data I want
return(
<div className="container">
<div>
<button onClick={fetchData}> Click to get data </button>
</div>
{(someBoolean == true && loading == false) ?
Some Action
: <></>
</div>
);
}
export default Sessions;
我也不确定你为什么要 [setDataFetch, setLoading, setSomeBoolean]
作为第一个 useEffect
的依赖数组?