【问题标题】:after using React Natives usestate function, includes method fails使用 React Natives 的 usestate 函数后,包含方法失败
【发布时间】: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>
);

【问题讨论】:

    标签: javascript react-native use-state asyncstorage


    【解决方案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(),这当然不会起作用,因为异步调用尚未通过。

      【讨论】:

        猜你喜欢
        • 2021-01-26
        • 2020-06-24
        • 1970-01-01
        • 2022-01-09
        • 1970-01-01
        • 1970-01-01
        • 2018-10-21
        • 2020-03-21
        • 1970-01-01
        相关资源
        最近更新 更多