无法在 React 中执行反应状态

Can't perform react state in React

我有问题。一直在这里浏览一些问题,但似乎对我不起作用。

我在使用 useEffect 时在我的三个页面中遇到此错误。

这是我的useEffect的代码

const UserDetailsPage = () => {


  const classes = useStyles()

  const [userData, setUserData] = useState({
    _id: "",
    name: "",
    phone: "",
    address: "",
    birthdate: "",
    gender: "",
    messenger: "",
    photo: "",
    email: "",
  })
  const [open, setOpen] = useState(false)
  const [loaded, setLoaded] = useState(false)
  const { height, width } = useWindowDimensions()

  const {
    _id,
    name,
    phone,
    address,
    photo,
    gender,
    messenger,
    birthdate,
    email,
  } = userData

  useEffect(() => {
    const user = getUser()

    getUserById("/user/" + user.userId, user.token)
      .then((data) => {
        setUserData(data)
        setLoaded(true)
      })
      .catch((error) => {
        console.log(error)
      })
  }, [])

这是因为 useEffect 中的异步调用完成,然后在页面不再处于焦点后 setState 尝试。

可以通过像这样重构 useEffect 来避免:

  useEffect(() => {
    // created a boolean to check if the component is mounted, name is arbitrary
    let mounted = true;

    const user = getUser();

    getUserById("/user/" + user.userId, user.token)
      .then((data) => {
        // only setState if mounted === true
        if (mounted) {
          setUserData(data);
          setLoaded(true);
        }
      })
      .catch((error) => {
        console.log(error);
      });

    // set mounted to false on cleanup
    return () => {
      mounted = false;
    };
  }, []);

这里的不同之处在于我使用 mounted 布尔值来检查页面当前是否已安装。通过将 setState 调用包装在 if 状态中,我可以检查 setState 是否安全,从而避免错误。

Additional reading

缺少 getUserById 返回取消令牌以取消任何进行中的网络请求或“取消订阅”方法,您可以使用 React ref 来跟踪组件是否仍在安装,而不是入队如果组件已经卸载,则状态更新。

const isMountedRef = React.useRef(false);

useEffect(() => {
  isMountedRef.current = true;
  return () => isMountedRef.current = false;
}, []);

useEffect(() => {
  const user = getUser();

  getUserById("/user/" + user.userId, user.token)
    .then((data) => {
      if (isMountedRef.current) {
        setUserData(data);
        setLoaded(true);
      }
    })
    .catch((error) => {
      console.log(error);
    });
}, []);

当您的组件在设置状态之前卸载时会发生这种情况。试试下面的代码来检查组件是否已安装。

useEffect(() => {
  let isMounted = true;   // add a flag to check component is mounted

  getUserById("/user/" + user.userId, user.token)
  .then((data) => {
    if(mounted) {  // set state only when component is mounted
       setUserData(data)
       setLoaded(true)
    }
  })
  .catch((error) => {
    console.log(error)
  })

  return () => { isMounted = false }; // cleanup toggles value, if unmounted
}, []);

不要在 useEffect 中使用异步任务。定义一个异步函数并在你的 useEffect 中调用。

示例:

const getSTH = async() =>{
    getUserById("/user/" + user.userId, user.token)
     .then((data) => {
        if(mounted) {  // set state only when component is mounted
        setUserData(data)
        setLoaded(true)
     }
    })
    .catch((error) => {
       console.log(error)
    })

}

useEffect (()=>{
    getSTH();
},[])

我认为这种方法会对你有所帮助。