使用 React Natives 的 usestate 函数后,包含方法失败

Posted

技术标签:

【中文标题】使用 React Natives 的 usestate 函数后,包含方法失败【英文标题】:after using React Natives usestate function, includes method fails 【发布时间】:2021-12-04 07:09:54 【问题描述】:

我正在尝试在我的 react 本机代码中包含一个收藏夹机制,但我遇到了一个问题:

当页面首先呈现时,favs.includes 函数按预期工作。但是当我点击收藏按钮时,它会引发错误

TypeError: favs.includes is not a function. (In 'favs.includes(id)', 'favs.includes' is undefined)

const getFavs = async () => 
  await AsyncStorage.getItem("favs").then((res) => 
    if (res !== [] && res !== null && res !== "") 
      return setFavs(JSON.parse(res));
     else 
      return setFavs([]);
    
  );
;
useEffect(() => 
  getFavs();
  console.log(favs.includes(id));
  return console.log(typeof favs);
, []);

return (
  <View style= alignItems: "center", justifyContent: "center" >
    favs.includes(id) ? (
      <TouchableOpacity
        onPress=() => 
          AsyncStorage.removeItem("favs", id);
        
      >
        <Icon name="star" size=25 color="orange" solid />
      </TouchableOpacity>
    ) : (
      <TouchableOpacity
        style= height: 100, width: 100, backgroundColor: "red" 
        onPress=() => 
          console.log(typeof favs);
          setFavs(favs.push(id));
          console.log(typeof favs);
          AsyncStorage.setItem("favs", JSON.stringify(favs));
          setFav(true);
        
      >
        <Icon name="star" size=25 color="orange" />
      </TouchableOpacity>
    )
  </View>
);

【问题讨论】:

【参考方案1】:

问题在于点击处理程序中的这一行

setFavs(favs.push(id))

favs 设置为数字而不是数组。 Array#push() 在 push 后返回数组的新长度,而不是数组本身。见Why does Array.prototype.push return the new length instead of something more useful?。

另外,在状态数组上使用 push() 会改变数组,您应该改为

setFavs(prevFavs => [...prevFavs, id])
// or
setFavs(prevFavs => prevFavs.concat(id))

您的最后一个错误是假设在您的 setState 调用之后调用 console.log 将反映状态的变化,而实际上它会记录旧的(当前)状态值。在下一个渲染周期之前,更新的状态值将不可用。见Why calling react setState method doesn't mutate the state immediately?

【讨论】:

【参考方案2】:

我认为这通常是因为组件最初渲染时,favs 状态仍然为空或getFavs 异步功能未完成。

也许您可以尝试为favs.includes 调用的位置提供条件,例如:

           favs && favs.includes && favs.includes(id)? // make sure favs is truthy and favs.includes property existed
            <TouchableOpacity onPress=()=>
                AsyncStorage.removeItem('favs',id);
            >
            <Icon name = "star" size=25 color="orange" solid />
            </TouchableOpacity >
            :
            <TouchableOpacity
            style=height:100,width:100,backgroundColor:'red' onPress=()=>
                console.log(typeof(favs))
                setFavs(favs.push(id))
                console.log(typeof(favs))
                AsyncStorage.setItem('favs',JSON.stringify(favs))
                setFav(true)
            >
            <Icon name = "star" size=25 color="orange" />
            </TouchableOpacity >
            

如果这能解决您的问题,请告诉我,谢谢

【讨论】:

感谢您的评论,这不是原因。 Pilchard 的方法成功了。【参考方案3】:

我发现您的代码有两个问题。

首先,我没有看到您的useState 用法。应该是

const [favs, setFavs] = useState([]);

其次,您正在混合异步和同步代码。您正在调用getFavs,其中包含对在主程序线程“外部”执行的异步存储的调用。之后您立即调用favs.includes(),这当然不会起作用,因为异步调用尚未通过。

【讨论】:

以上是关于使用 React Natives 的 usestate 函数后,包含方法失败的主要内容,如果未能解决你的问题,请参考以下文章

React Hooks 中的闭包问题

React Hooks 中的闭包问题

react常用模块介绍

如何使用 React-Bootstrap 和 Redux 显示/隐藏 Modal?

react hooks useState 赋值优化解决方案

"natives"啥意思