获取请求后无法更新状态
Posted
技术标签:
【中文标题】获取请求后无法更新状态【英文标题】:Can't Update state after fetch request 【发布时间】:2022-01-20 23:22:22 【问题描述】:我正在尝试制作一个应用程序,从 Graphql API 获取数据,并在获取后更新状态,但在成功请求后我获取了数据,但我无法使用该数据更新状态。当我控制台记录响应数据时,它会显示包含所需数据的数组,但是当我更新状态并控制台记录状态时,它会显示空数组。
我需要更新状态以在组件中使用它,当我这样做时会抛出 currList 未定义的错误。
这里是代码和控制台的图片。
export default function App()
const [search, setSeach] = useState("");
const [currList, setCurrList] = useState([]);
const fetchShips = async () =>
const response = await request(gql`
ships
name
home_port
image
`);
console.log("request response", response.data);
setCurrList(response.data);
console.log("currlist:", currList);
;
useEffect(() =>
fetchShips();
, [currList]);
const Searchitems = (event) =>
setSeach(event.target.value);
setCurrList(
currList.filter((item) =>
return item.name.includes(search) || item.home_port.includes(search);
)
);
;
return (
<div className="App">
<div className="container">
<header></header>
<div className="body">
<input
type="text"
id="search"
value=search
onChange=Searchitems
className="input"
placeholder="Search Ships"
/>
<p>Total Count: currList.length</p>
<div className="ships">
currList.map((item, index) =>
return (
<Ship
key=index
name=item.name
port=item.port
img=item.image
/>
);
)
</div>
</div>
</div>
</div>
);
【问题讨论】:
已设置,但 setCurrList 是异步的,您可以通过将其记录到 useEffect 中来查看 currList 状态 尝试登录到useEffectuseEffect(()=> console.log(currList),[currList])
【参考方案1】:
状态只是在代码运行时更新,这就是它记录状态为空数组的原因,尝试再次控制台记录它,您会看到列表中有一些东西。
【讨论】:
【参考方案2】:这很正常,一切都是异步发生的。一旦您的 currList 更新,React 将触发重新渲染,您将获得它的新值。如果你想听这个变化,你必须使用 useEffect 和 currList 作为依赖。
useEffect(() =>
console.log("List is updated", currList);
, [currList]);
【讨论】:
我需要状态来渲染组件,我该怎么做?当我使用上面的代码时,它会抛出错误“currList.map 不是函数”和“无法读取未定义(长度)的属性”。? 首先,关于您共享的代码,useEffect 应该有一个空数组作为依赖项,因为您只想为第一次渲染调用 fetchShips useEffect(() => fetchShips(); , []); 在搜索输入中输入之后或之前是否看到错误? 我在输入搜索输入之前看到错误,该错误显示在组件渲染中 你能看到这一行执行了吗:console.log("request response", response.data); ?控制台中显示了什么?【参考方案3】:函数 fetchShips 对特定渲染调用的 currList 状态变量有闭包,因此当您在调用 setCurrList 后记录它时,它会显示之前的状态而不是更新的状态,您可以将其记录在 useEffect 中以查看更改.
【讨论】:
【参考方案4】:我曾经遇到过同样的问题。我找不到有效的解决方案,但我的解决方案还是救了我。
我使用了 useRef 而不是 useState。 试试这个:
const currList = useRef([]);
useEffect=(()=>
const fetchShips = async () =>
const response = await request(gql`
ships
name
home_port
image
`);
console.log("request response", response.data);
// setCurrList(response.data);
if(response)
currlist.current = response.data
console.log("currlist:", currList);
;
fetchShips()
// Also as far as I know ,you should use useEffect like this
,[])
//... codes
return(
//... codes
currList.current.map(...
)
//... codes
在使用 useRef 之前,请尝试在 useEffect 中定义您的 fetchShips 函数,这样也许您不需要我的解决方案。
为什么我的解决方案对您的情况无效? 当您想要更新您的 currList 数据时,useRef 不会触发重新渲染。即使您的数据已更新,您也无法在屏幕上看到它。 所以 setCurrList(currList.current) 可以拯救你,但正如我之前所说,它可能不是有效的方法。
【讨论】:
以上是关于获取请求后无法更新状态的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使在有状态小部件中使用 setstate 也无法获取更新的变量。因为我想在新的 TabBar 选项上更新我的 Container